VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
Data Type and Default Differences
MariaDB-Only Schema Objects Break the Load
A schema that usesCREATE SEQUENCE fails immediately when loaded into MySQL, before any table is created, because mysqldump writes sequence definitions ahead of tables. Loading an unmodified dump containing a sequence produces this, where the at line N values track where the statement sits in your own dump and will not match the numbers shown here:
DROP SEQUENCE / CREATE SEQUENCE / DO SETVAL(...) block from the dump, and replace any column default that reads DEFAULT nextval(...) with a plain AUTO_INCREMENT column or an application-assigned value.
A column typed INET6 fails the same way, later in the same load, once the loader reaches the table that declares it. This is the one error in this guide whose wording depends on which server you load into. VillageSQL names the type, because its grammar accepts custom type names in that position and reports the one it could not resolve:
ERROR 1064, and both name the offending line, so the fix is the same either way. Change the column type to VARCHAR(45) (long enough for an IPv6 address in text form) before loading, or to an INET type provided by an extension if one is installed on the target.
Foreign Key Constraint Names Collide Across Tables
mysqldump on MariaDB auto-names an unnamed foreign key constraint with a plain integer, starting from 1 again for every table. Two tables in the same schema can both end up with a constraint literally named 1:
CONSTRAINT 1“ fails with:
CONSTRAINT name given in the CREATE TABLE). Rename each colliding constraint to something unique, for example order_items_ibfk_1 and orders_ibfk_1, before loading.
The JSON Column Loads Without Error, as a Different Type
Unlike the three issues above, aJSON column loads into MySQL with no error and no warning. The dumped CREATE TABLE for a MariaDB JSON column looks like this:
CHECK constraints and the JSON_VALID() function, so this statement runs as written. The column ends up as LONGTEXT with a CHECK constraint on the MySQL side, not as MySQL’s native JSON type. Reading it back with JSON_EXTRACT() and JSON_LENGTH() gives identical results to the source data, so nothing is lost, but the column’s declared type is different from what a fresh MySQL schema would use. If you want the native JSON type on the target, alter the column after loading:
CHECK (json_valid(...)) constraint attached to the column. The dump does not name that constraint, so the server named it when the CREATE TABLE ran, something like products_chk_1; it is already there before the ALTER. It’s harmless on a native JSON column, since MySQL already rejects invalid JSON at the type level, but it’s dead weight left over from the LONGTEXT definition. Drop it if you want a clean schema:
Authentication Differences
MariaDB and MySQL clients speak the same wire protocol, and a plain password-authenticated connection from one to the other works. What does not carry over is the account definition itself.mysqldump does not dump the mysql.user table by default, so accounts and grants have to be recreated by hand on the target, and the syntax for doing so differs.
A MariaDB account created with a password shows up like this:
caching_sha2_password plugin, looks like this instead:
SHOW CREATE USER statement from MariaDB into MySQL. Create the account fresh with CREATE USER ... IDENTIFIED BY '<password>' on the target and let it pick its own default plugin, then reissue the GRANT statements.
If you’re testing a migration against a MariaDB install you just set up (a fresh Homebrew install, for example), and a named account with a password gets rejected with “Access denied” even though the password is right, check for anonymous accounts first:
''@'localhost' and ''@'<hostname>' in place. Because host matching is more specific than username matching, a connection that resolves to localhost matches the anonymous account before it matches your named one, and gets rejected because the anonymous account expects no password. This is a MariaDB source-install issue, not something that follows the data into MySQL, but it can make source-side testing confusing until the anonymous accounts are dropped.
Migration Approach
- Dump the schema and data with
mysqldump(on a MariaDB host this is usually a symlink to MariaDB’s ownmariadb-dump; runmysqldump --versionto confirm which one you have). - Scan the dump for
CREATE SEQUENCE,INET6, andRETURNINGbefore attempting a load. None of the three produce a useful error until the load is already partway through. - Attempt a load into a scratch database first. A
CREATE SEQUENCEorINET6failure aborts the whole script at that statement, so tables defined earlier in the file are already loaded and tables defined later are not. Fix the dump and reload into a fresh database rather than patching a half-loaded one. - Check for foreign key constraint name collisions if the source schema relied on unnamed foreign keys.
grep -o 'CONSTRAINT \[0-9]*`’ dump.sql` finds them. - Recreate accounts and grants by hand.
mysqldumpdoes not carry them, and theCREATE USER/SHOW CREATE USERsyntax differs between the two servers. - Verify row counts and spot-check any JSON columns. A
JSONcolumn loads silently asLONGTEXT; confirm the data round-trips withJSON_EXTRACT()before deciding whether to convert it to a nativeJSONcolumn.
Frequently Asked Questions
Does a MariaDB mysqldump file need any edits for a same-version-family MySQL target?
If the schema doesn’t use sequences, INET6, RETURNING, or unnamed foreign keys, the same dump often loads without changes. Test the load against a scratch database first rather than assuming it will succeed based on the schema being “just tables and data.”
Will a native MySQL JSON column round-trip through a MariaDB dump correctly?
Values round-trip correctly. The column type does not: MariaDB dumps its JSON columns as LONGTEXT with a CHECK constraint, and that is exactly what loads into MySQL, unless you explicitly ALTER TABLE ... MODIFY the column to JSON afterward.
Can I connect to a MariaDB server with a MySQL client, or the reverse?
Yes, for ordinary password-authenticated connections. Both use the same wire protocol, and a client built against one library can authenticate against an account on the other server, once the account itself exists with a password. The SQL each server accepts is where they diverge, not the connection.Troubleshooting
See also
- Migrating from PostgreSQL to MySQL — the equivalent guide for a PostgreSQL source
- Schema Migrations in MySQL — running the DDL changes a migration requires

