Migrate MariaDB to Oracle
Beta — live-tested pathMigrating from MariaDB (the community-driven MySQL fork) to Oracle (Oracle Database, the long-standing enterprise standard) means every table, column type, key, index and row has to survive two engines' different opinions about data. DBShifts converts the schema with deterministic rules, transfers data in parallel batches, and validates the result with per-table row counts and type-aware checksums.
Free tier · no credit card
MariaDB vs Oracle
MariaDB
the community-driven MySQL fork.
Oracle
Oracle Database, the long-standing enterprise standard.
How the migration works
Connect
Point DBShifts at your source and target. Credentials stay encrypted; SSH tunnels supported for private databases.
Analyze
Automatic schema introspection produces a migration plan: what converts automatically, what migrates with warnings, what needs human review.
Migrate
Schema is created on the target, data transfers in parallel batches with constraints deferred, indexes rebuilt after load.
Validate
Per-table row counts, type-aware checksums on both sides, FK integrity — plus a fidelity report listing anything lossy.
MariaDB to Oracle data type mapping
Pulled directly from DBShifts's own conversion rules — not a general reference table, this is what actually runs.
| MariaDB | Oracle |
|---|---|
| INT | NUMBER(10) |
| BIGINT | NUMBER(19) |
| SMALLINT | NUMBER(5) |
| TINYINT(1) | NUMBER(1) |
| DECIMAL(10,2) | NUMBER(10,2) |
| FLOAT | BINARY_FLOAT |
| DOUBLE | BINARY_DOUBLE |
| VARCHAR(255) | VARCHAR2(255 CHAR) |
| TEXT | CLOB |
| LONGTEXT | CLOB |
| CHAR(10) | CHAR(10 CHAR) |
| DATE | DATE |
| DATETIME | TIMESTAMP |
| TIMESTAMP | TIMESTAMP WITH TIME ZONE |
| TIME | VARCHAR2(18) |
| YEAR | NUMBER(4) |
| BLOB | BLOB |
| JSON | CLOB |
| ENUM('a','b') | VARCHAR2(255) |
| SET('a','b') | VARCHAR2(4000) |
Example: MariaDB to Oracle schema conversion
MariaDB
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
status ENUM('new','paid','shipped') NOT NULL DEFAULT 'new',
total DECIMAL(10,2) NOT NULL,
is_gift TINYINT(1) NOT NULL DEFAULT 0,
notes TEXT,
metadata JSON,
placed_at DATETIME NOT NULL
);Oracle
CREATE TABLE "orders" (
"id" NUMBER(10) NOT NULL,
"customer_id" NUMBER(10) NOT NULL,
"status" VARCHAR2(255),
"total" NUMBER(10,2) NOT NULL,
"is_gift" NUMBER(1),
"notes" CLOB,
"metadata" CLOB,
"placed_at" TIMESTAMP NOT NULL,
CONSTRAINT pk_orders PRIMARY KEY ("id")
);Identifier length, case and quoting
Oracle folds unquoted identifiers to uppercase, and MariaDB does not. A table created as customer_orders in MariaDB becomes CUSTOMER_ORDERS in Oracle unless it is quoted, and quoting it preserves the lowercase name at the cost of requiring quotes in every query from then on. Choose one convention before converting, because mixing them produces tables that appear to exist and cannot be selected from.
Identifier length is the other constraint. Oracle allowed 30 bytes before 12.2 and 128 after, while MariaDB allows 64 characters. Long generated names, particularly for foreign keys and indexes, are the ones that overflow, and they overflow at DDL time rather than during the data load.
Case sensitivity in data, not just in names
MariaDB's default collation is case-insensitive, so 'ACME' and 'acme' are equal in a WHERE clause and cannot both exist in a unique index. Oracle compares strings case-sensitively by default. After migration, queries that matched on mixed case stop matching, and a unique index that rejected a duplicate on MariaDB will accept it on Oracle.
That second effect is the dangerous one, because it does not fail. It quietly permits data the source considered duplicate, and the divergence grows from the moment the application starts writing to Oracle.
Text types, and why TEXT becomes CLOB
MariaDB TEXT holds up to 65,535 bytes and LONGTEXT up to 4GB, while Oracle VARCHAR2 stops at 4000 bytes in standard SQL semantics. Anything above that has to become CLOB, which is why the table above maps TEXT to CLOB rather than to a large VARCHAR2.
CLOB is not a drop-in replacement. It cannot be indexed like a VARCHAR2, comparison semantics differ, and some drivers require explicit handling to read it. A column that is declared TEXT but never exceeds a few hundred characters is much better converted to VARCHAR2, so it is worth measuring the real maximum length per column rather than trusting the declared type.
Oracle also counts VARCHAR2 in bytes by default rather than characters. A 255-character column holding multi-byte UTF-8 needs VARCHAR2(255 CHAR) or it will reject rows that fit comfortably in MariaDB.
MariaDB → Oracle conversion notes
Engine-specific rules baked into the conversion and transfer pipeline — verified by live certification of this exact pair.
- MariaDB's JSON columns (LONGTEXT + json_valid CHECK) are detected and mapped to real JSON types on targets that have them.
- Engine-specific CHECK constraints like json_valid() are filtered on targets that don't support them — data still migrates.
- Display-width unsigned types (bigint(20) unsigned) are recognized and widened correctly.
- CHAR columns use character semantics, so multi-byte UTF-8 doesn't overflow byte-sized columns.
- Booleans land as NUMBER(1) with values bound as integers (Oracle drivers can't bind Python booleans to NUMBER).
- DROP TABLE … CASCADE CONSTRAINTS wrappers handle re-runs without manual cleanup.
Frequently asked questions
Is MariaDB to Oracle migration production-ready in DBShifts?
MariaDB to Oracle is a live-verified beta pair: it passed the same certification suite as every other pair — a real migration with edge-case data validated by row counts and checksums — and ships with a post-migration fidelity report you can audit before cutover.
How does DBShifts verify the MariaDB to Oracle migration was correct?
Three layers: per-table row counts on both sides, an order-independent type-aware checksum of row data (canonicalized so engine representation differences don't false-alarm), and FK integrity checks on the target. Rows that fail to insert are quarantined with the exact error — never silently dropped — and can be fixed and retried from the UI.
What happens to MariaDB types that Oracle doesn't have?
They convert by deterministic rules with a recorded decision: a native equivalent where one exists, a portable fallback (TEXT/JSON/DECIMAL) where one doesn't. Every lossy conversion appears in the migration plan before you run and in the fidelity report after. You can override any mapping per column.
Can I keep MariaDB and Oracle in sync after the initial migration?
Yes. DBShifts supports incremental sync (UPSERT-based delta transfers on a sync key) and, for supported sources, real-time change data capture so the target stays current until you cut over.
Do I need to write any SQL or scripts for MariaDB to Oracle?
No. Connect both databases, review the generated migration plan (what's automatic, what migrates with warnings, what needs manual review — typically triggers and stored procedures), and run. Procedural code is transpiled best-effort and queued for human review rather than auto-applied.
What's the hardest part of moving MariaDB to Oracle?
Type-system mismatches that fail silently rather than loudly — MariaDB's edge-case types (3 engine-specific rules apply) converting into Oracle's nearest equivalent. DBShifts's deterministic mapping records every downgrade in the fidelity report, so a value that clips, rounds, or widens is visible before cutover, not after.
Which MariaDB data types change when moving to Oracle?
9 of the mapped types convert to something that cannot represent exactly the same range or constraint. The clearest cases are TINYINT(1) to NUMBER(1), FLOAT to BINARY_FLOAT, DOUBLE to BINARY_DOUBLE. The full table above lists every mapping the converter performs, and analysis flags each one on your actual schema before any data moves.
Go deeper
Related migration paths
Ready to move MariaDB to Oracle?
Set up in under two minutes. Validation and rollback included.
Start Free Migration