
MariaDB and MySQL share a common ancestor and most of their syntax. For small databases with simple schemas, moving from one to the other can feel trivial. Run a dump, restore it, done.
That assumption breaks in production.
MariaDB has been diverging from MySQL since its fork in 2009. Seventeen years of independent development means MariaDB now has features, data types, functions, and storage engines that simply do not exist in MySQL. When a dump of a MariaDB database hits a MySQL 8.0 instance, it either imports with silent data inconsistencies, fails partway through on unrecognized syntax, or succeeds on the surface while leaving behind broken application behavior that only shows up under specific query conditions.
This guide is built around that reality. Before covering the migration methods themselves, it covers exactly what breaks and why, so you can audit your schema and application before touching a single byte of production data. Then it walks through three methods depending on whether you need a one-time migration, a guided schema conversion, or an ongoing real-time sync between MariaDB and MySQL.
If you are here because your migration already failed and you are debugging errors, the compatibility checklist and troubleshooting sections are where you want to start.
MariaDB vs MySQL: Key Differences That Affect Migration
Most compatibility problems fall into five categories. Knowing which ones apply to your database before you start saves hours of debugging after.
Data Type Differences
MariaDB has data types that do not exist in MySQL or behave differently enough to cause problems on import.
UUIDis a native data type in MariaDB 10.7 and later. MySQL has no native UUID type. MariaDB stores UUIDs in a compact 16-byte binary format internally. When exported and imported into MySQL, UUID columns need to be converted toCHAR(36)orBINARY(16)depending on how your application reads them.INET6is a MariaDB-native type for storing IPv6 addresses. MySQL has no equivalent. You need to convertINET6columns toVARBINARY(16)orVARCHAR(39)before migration and update any application code that uses MariaDB's built-inINET6functions.JSONbehaves differently between the two databases. Both support JSON columns but MariaDB's JSON type is an alias forLONGTEXTwith a validity check, while MySQL stores JSON in a binary format that enables partial updates and path-based indexing. Data migrates but JSON indexing behavior changes and applications using MySQL's JSON path operators may need testing.
MariaDB-Only Features That Do Not Exist in MySQL
These are the features most likely to cause a hard failure during migration rather than silent data problems.
- Sequences are first-class objects in MariaDB, created with
CREATE SEQUENCE. MySQL has no sequence object. If your schema uses sequences for key generation, you need to replace them withAUTO_INCREMENTcolumns or application-level UUID generation before migration. - System-versioned tables use
WITH SYSTEM VERSIONINGsyntax to maintain full row history automatically. MySQL has no equivalent feature. If you have system-versioned tables, you need to decide whether to drop the versioning and migrate only the current state, or implement a custom audit log pattern in MySQL before migrating. - Invisible columns work differently. MariaDB invisible columns are excluded from
SELECT *results but exist in the table. MySQL 8.0.23 added invisible columns but with different behavior and syntax. Test invisible column definitions explicitly before migrating. - MariaDB-specific storage engines including TokuDB, Spider, Connect, and Columnstore do not exist in MySQL. Tables using these engines need to be converted to InnoDB before migration or handled with a custom export strategy.
SQL Syntax Differences
Several SQL constructs valid in MariaDB produce errors in MySQL.
RETURNINGclause inINSERT,UPDATE, andDELETEstatements is supported in MariaDB 10.5 and later but does not exist in MySQL. Application queries usingRETURNINGneed to be rewritten before or after migration.LIMITin subqueries is supported in MariaDB but restricted in MySQL. Queries usingLIMITinside a subquery without a wrapping derived table fail in MySQL with an error.DEFAULTexpressions using functions work differently. MariaDB allows any deterministic function as a column default, includingUUID(),NOW(), and custom functions. MySQL 8.0 expanded support for expression defaults but there are still MariaDB-specific functions that MySQL does not recognize.
Character Set and Collation Differences
This is the most common source of silent data corruption in MariaDB to MySQL migrations.
- MariaDB defaults to
utf8mb4withutf8mb4_general_cicollation in recent versions. MySQL 8.0 defaults toutf8mb4withutf8mb4_0900_ai_cicollation. These collations sort and compare strings differently. A migration that does not explicitly set collation will produce a MySQL database that sorts query results differently from the MariaDB source, which breaks any application logic that depends on sort order being consistent. - More critically,
utf8mb3andutf8mb4are different character sets. MariaDB historically treatedutf8as an alias forutf8mb3, a 3-byte encoding that cannot store 4-byte Unicode characters, including most emoji. MySQL 8.0 deprecatedutf8mb3and treatsutf8asutf8mb4. A database migrated without explicit character set declarations can end up with mixed encodings that cause query failures on 4-byte characters.
Always declare character sets and collations explicitly in your migration. Never rely on server defaults to remain consistent between MariaDB and MySQL.
Authentication and User Management
MySQL 8.0 changed its default authentication plugin from mysql_native_password to caching_sha2_password. MariaDB uses mysql_native_password by default. After migration, existing application database connections may fail with authentication errors until the MySQL user accounts are updated to use the correct authentication plugin or the MySQL server is configured to accept mysql_native_password connections.
If your application uses an older MySQL client library that does not support caching_sha2_password, configure MySQL to use mysql_native_password as the default:
plaintext language-sql-- In MySQL 8.0 my.cnf
[mysqld]
default_authentication_plugin=mysql_native_password
Note that mysql_native_password is deprecated in MySQL 8.4 and removed in MySQL 9.0. For new migrations targeting MySQL 8.4 or later, update application client libraries to support caching_sha2_password rather than configuring the legacy plugin.
Pre-Migration Compatibility Checklist
Run these checks against your MariaDB instance before starting any migration method. Each query identifies objects or settings that need attention before data moves.
Check for MariaDB-only data types:
plaintext language-sqlSELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'your_database'
AND data_type IN ('uuid', 'inet6', 'inet4');
Any results need manual type conversion before migration.
Check for sequences:
plaintext language-sqlSELECT sequence_name FROM information_schema.sequences
WHERE sequence_schema = 'your_database';
Replace sequences with AUTO_INCREMENT or application-level generation before migrating.
Check for system-versioned tables:
plaintext language-sqlSELECT table_name FROM information_schema.tables
WHERE table_schema = 'your_database'
AND table_type = 'SYSTEM VERSIONED';
Decide whether to migrate current state only or implement a MySQL audit log alternative.
Check for non-InnoDB storage engines:
plaintext language-sqlSELECT table_name, engine
FROM information_schema.tables
WHERE table_schema = 'your_database'
AND engine NOT IN ('InnoDB', 'MyISAM', 'MEMORY', 'CSV');
Tables using TokuDB, Spider, Connect, or Columnstore need converting to InnoDB before migration.
Check character sets and collations:
plaintext language-sqlSELECT table_name, table_collation
FROM information_schema.tables
WHERE table_schema = 'your_database'
AND table_collation NOT LIKE 'utf8mb4%';
Any non-utf8mb4 collations need explicit handling during migration.
Check for LIMIT in subqueries:
This requires a code-level review rather than a database query. Search your application codebase and stored procedures for patterns like WHERE id IN (SELECT id FROM table LIMIT n) and rewrite them as derived tables before migrating.
Check binary log format (required for CDC methods):
plaintext language-sqlSHOW VARIABLES LIKE 'binlog_format';
Must return ROW for Estuary CDC to work. Change if needed:
plaintext language-sqlSET GLOBAL binlog_format = 'ROW';
Method 1: Migrate MariaDB to MySQL Using mysqldump
mysqldump is the most direct way to migrate MariaDB to MySQL for one-time migrations. It exports your database to a SQL file and imports it into MySQL. For databases under a few GB with no MariaDB-specific features identified in the checklist above, this is the fastest path.
Prerequisites:
mysqldumpinstalled on the source MariaDB server or a machine with network access to it- MySQL 5.7 or later on the destination
- Enough disk space for the dump file, at minimum equal to the uncompressed database size
Step 1: Export from MariaDB
plaintext language-bashmysqldump \\
--user=your_user \\
--password \\
--host=your_mariadb_host \\
--single-transaction \\
--routines \\
--triggers \\
--set-gtid-purged=OFF \\
--default-character-set=utf8mb4 \\
your_database > mariadb_dump.sql
Key flags explained:
-single-transactiontakes a consistent snapshot without locking tables, safe for InnoDB tables on a live database-routinesincludes stored procedures and functions in the dump-triggersincludes triggers-set-gtid-purged=OFFprevents MariaDB GTID information from being written into the dump file, which MySQL cannot parse and which causes import failures-default-character-set=utf8mb4ensures the dump file is written inutf8mb4encoding
Step 2: Clean MariaDB-specific syntax from the dump
Before importing, remove or replace syntax that MySQL does not recognize:
plaintext language-bash# Remove MariaDB-specific comments and version locks
sed -i 's/\\/\\*M!100\\([0-9]*\\).*\\*\\///' mariadb_dump.sql
# Remove NO_AUTO_CREATE_USER from sql_mode if present
sed -i 's/NO_AUTO_CREATE_USER,//' mariadb_dump.sql
sed -i 's/,NO_AUTO_CREATE_USER//' mariadb_dump.sql
If the checklist identified utf8mb3 collations, replace them explicitly:
plaintext language-bashsed -i 's/utf8mb3/utf8mb4/g' mariadb_dump.sql
sed -i 's/utf8_general_ci/utf8mb4_general_ci/g' mariadb_dump.sql
Step 3: Import into MySQL
plaintext language-bashmysql \\
--user=your_user \\
--password \\
--host=your_mysql_host \\
--default-character-set=utf8mb4 \\
your_database < mariadb_dump.sql
For large dumps, run the import inside a screen or tmux session to prevent disconnection from killing the process mid-import.
Step 4: Handle authentication after import
If your MariaDB user accounts were included in the dump and MySQL 8.0 is the destination, update authentication plugins after import:
plaintext language-sqlALTER USER 'your_app_user'@'%'
IDENTIFIED WITH mysql_native_password
BY 'your_password';
FLUSH PRIVILEGES;
Limitations:
mysqldump produces a point-in-time snapshot. Any writes to MariaDB after the dump starts are not captured. For databases with continuous write traffic, this means a cutover window where the application must be stopped or set to read-only while the dump and import complete. For large databases, this window can be hours long. If minimizing downtime is a requirement, use Estuary instead.
Method 2: Migrate MariaDB to MySQL Using MySQL Workbench Migration Wizard
MySQL Workbench includes a built-in Migration Wizard designed specifically for migrating databases between different MySQL-compatible systems including MariaDB. Unlike mysqldump which exports raw SQL that may contain incompatible syntax, the Migration Wizard inspects the source schema, maps object types to their MySQL equivalents, flags compatibility issues before migration starts, and lets you edit the generated MySQL schema before any data moves.
For teams who prefer a visual workflow or who have already identified compatibility issues in the checklist and need help resolving them, the Migration Wizard is the right tool.
Prerequisites:
- MySQL Workbench 8.0 or later installed on your local machine
- Network access to both the MariaDB source and MySQL destination from the machine running Workbench
- A MariaDB user with
SELECT,SHOW VIEW,TRIGGER, andLOCK TABLESprivileges - A MySQL destination user with
CREATE,ALTER,INSERT,UPDATE,DELETE, andDROPprivileges
Step 1: Open the Migration Wizard
In MySQL Workbench, go to Database in the top menu and select Migration Wizard. The wizard opens and walks you through the migration in stages.
Step 2: Configure the source connection
Select MySQL as the source database system. Despite the label, MySQL Workbench recognizes MariaDB connections through the MySQL protocol. Enter your MariaDB connection details:
- Hostname and port
- Username and password
- Default schema if migrating a single database
Click Next and test the connection. Workbench connects to MariaDB and fetches the list of available schemas.
Step 3: Configure the destination connection
Enter your MySQL destination connection details in the same format. Click Next and test the destination connection.
Step 4: Select schemas to migrate
Workbench displays all schemas available on the MariaDB source. Select the database you want to migrate. You can select multiple schemas in a single migration run.
Step 5: Review object mapping
This is the most valuable step in the wizard. Workbench inspects the source schema and generates a MySQL-compatible version of every object including tables, views, stored procedures, triggers, and indexes. It flags any objects it could not convert automatically in a summary screen.
Review the flagged objects carefully. Common items flagged here include:
- MariaDB-specific functions used in column defaults
- Storage engines without a MySQL equivalent
- Character set or collation mismatches
- Syntax in stored procedures that MySQL does not support
For each flagged object, Workbench lets you edit the generated MySQL SQL directly in the wizard before proceeding. Fix compatibility issues here rather than after import.
Step 6: Run the migration
After reviewing and editing the schema, click Next to proceed through the data transfer stages. Workbench runs the migration in this order: creates the schema objects in MySQL, transfers table data, then creates indexes and constraints.
The progress screen shows row counts per table and flags any errors that occur during data transfer. Common errors at this stage are character set conflicts and row size limits, both of which surface here with specific table and column names.
Step 7: Generate a migration report
After the migration completes, Workbench generates a full report listing every object migrated, every object that failed, and every manual change made during the schema review step. Save this report before closing the wizard as it is the most complete record of what changed during migration.
Limitations:
Like mysqldump, the Migration Wizard performs a point-in-time migration. Writes to MariaDB during the migration are not captured in MySQL. The wizard also has a row size limit for its data transfer mechanism that can cause failures on tables with very wide rows or large BLOB columns. For those tables, supplement the wizard migration with a separate mysqldump of the affected tables.
For databases larger than approximately 50GB the wizard becomes slow compared to mysqldump with direct file transfer. At that scale mysqldump or Estuary is the more practical choice.
Method 3: Continuously Sync MariaDB to MySQL Using Estuary CDC
The first two methods are point-in-time migrations. They require a cutover window, produce downtime, and give you no path back if something goes wrong after the switch. Estuary works differently. It uses Change Data Capture via the MariaDB binary log to continuously sync every insert, update, and delete from MariaDB to MySQL in real time, keeping both databases in sync simultaneously until you are ready to cut over with confidence.
This approach suits three specific situations: databases too large for an acceptable downtime window, teams that need a live parallel run period to validate data correctness before cutting over, and ongoing sync use cases where MariaDB and MySQL need to stay in sync permanently.
Prerequisites
On the MariaDB source:
The binary log must be enabled and configured correctly. Check your current settings:
plaintext language-sqlSHOW VARIABLES LIKE 'binlog_format';
SHOW VARIABLES LIKE 'expire_logs_days';
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
binlog_format must return ROW. If it does not, set it in your MariaDB configuration file:
plaintext[mysqld]
binlog_format = ROW
Binary log retention must be at least 7 days. The recommended value is 30 days. Set this in my.cnf:
plaintext[mysqld]
binlog_expire_logs_seconds = 2592000 # 30 days
If your MariaDB time_zone server variable is set to SYSTEM and you have DATETIME columns to capture, you must set an explicit timezone. Estuary cannot detect the timezone when it is set to SYSTEM:
plaintext language-sql-- Set explicitly using UTC offset
SET GLOBAL time_zone = '+00:00';
Or set it permanently in my.cnf:
plaintext[mysqld]
default_time_zone = '+00:00'
Create a dedicated capture user with the minimum required permissions:
plaintext language-sqlCREATE USER 'estuary_capture'@'%' IDENTIFIED BY 'your_password';
GRANT REPLICATION CLIENT ON *.* TO 'estuary_capture'@'%';
GRANT REPLICATION SLAVE ON *.* TO 'estuary_capture'@'%';
GRANT SELECT ON your_database.* TO 'estuary_capture'@'%';
-- Required for automatic table discovery
GRANT SELECT ON information_schema.* TO 'estuary_capture'@'%';
FLUSH PRIVILEGES;
Allowlist Estuary's IP addresses in your MariaDB firewall or security group. The full list is here.
On the MySQL destination:
Enable local_infile on the MySQL server, which the Estuary MySQL materialization connector requires for efficient bulk loading:
plaintext language-sqlSET GLOBAL local_infile = true;
Make it permanent in my.cnf:
plaintext[mysqld]
local_infile = 1
Create a dedicated materialization user with the required privileges:
plaintext language-sqlCREATE USER 'estuary_materialize'@'%' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON your_database.* TO 'estuary_materialize'@'%';
FLUSH PRIVILEGES;
Set the MySQL time_zone explicitly if you have DATETIME columns, for the same reason as the MariaDB source:
plaintext language-sqlSET GLOBAL time_zone = '+00:00';
Allowlist Estuary's IP addresses in your MySQL firewall or security group.
Step 1 — Create an Estuary Account
Go to dashboard.estuary.dev and register for a free account using Google or GitHub credentials.
Step 2 — Create a MariaDB Capture
Click Sources in the left navigation, then New Capture. Search for MariaDB in the connector catalog.
If you are running Amazon RDS for MariaDB, select the dedicated RDS for MariaDB connector variant instead of the standard MariaDB connector. The RDS variant handles the RDS-specific binary log retention command automatically:
plaintext language-sql-- RDS MariaDB uses this instead of binlog_expire_logs_seconds
CALL mysql.rds_set_configuration('binlog retention hours', 168);
For Azure Database for MariaDB, select the standard MariaDB connector and configure SSH tunneling if your Azure instance does not allow direct inbound connections.
Fill in the connection details:
- Address: Your MariaDB hostname and port in the format
hostname:3306. Default port is 3306. - User:
estuary_captureor the user you created above - Password: The password for that user
- Database: The specific database to capture from
Click Next. Estuary tests the connection and, if successful, runs automatic discovery, detecting all tables available for capture in the specified database.
Step 3 — Select Tables and Configure Capture Mode
Estuary displays all discovered tables. All are selected by default. Deselect any tables you do not need in MySQL.
By default Estuary first performs a complete backfill of each selected table, capturing the current state of all rows, before switching to real-time binary log CDC. This ensures MySQL has a complete dataset before live changes begin flowing.
For very large tables where a full backfill would be impractical, you can disable backfill on a per-table basis in the bindings configuration. This causes Estuary to skip the initial scan and capture only changes that occur after the capture starts. Use this only for tables where the existing data will be handled through a separate mysqldump import.
Click Save and Publish. Estuary immediately begins the backfill and simultaneously starts listening for binary log events so no changes are missed during the initial load.
Step 4 — Create a MySQL Materialization
Click destinations from the capture confirmation screen, then New Materialization. Search for MySQL in the connector catalog and select it.
Fill in the MySQL connection details:
- Address: Your MySQL hostname and port in the format
hostname:3306 - User:
estuary_materializeor the user you created above - Password: The password for that user
- Database: The target database in MySQL
For Amazon RDS for MySQL, use the RDS endpoint as the address. For Google Cloud SQL for MySQL, use the Private IP address. The port is always 3306 for both.
Click Next. Estuary displays the collection bindings, mapping each MariaDB table to a corresponding MySQL table. By default target table names match source table names. Rename them at this stage if your MySQL schema uses different naming conventions.
Step 5 — Configure Update Mode
For each binding you can choose between standard updates and delta updates.
Standard updates are the default. Estuary materializes each table as a current-state mirror of the MariaDB source, merging inserts, updates, and deletes into the MySQL target table. This is the correct choice for most MariaDB to MySQL migration and sync use cases.
Delta updates write every change event as a separate row rather than merging into current state. This suits audit log use cases where you need a complete event history rather than current state. For a straightforward migration, leave this as the default standard updates.
Click Save and Publish to activate the materialization.
Step 6 — Verify the Pipeline
After publishing, verify data is flowing correctly before making any application changes.
Check row counts match between MariaDB and MySQL once the initial backfill completes:
plaintext language-sql-- Run on MariaDB
SELECT COUNT(*) FROM your_database.your_table;
-- Run on MySQL
SELECT COUNT(*) FROM your_database.your_table;
Test real-time sync by inserting a row in MariaDB and querying MySQL for it within seconds:
plaintext language-sql-- Insert on MariaDB
INSERT INTO your_table (name, status) VALUES ('sync_test', 'active');
-- Query on MySQL within 5 seconds
SELECT * FROM your_table WHERE name = 'sync_test';
If the row appears in MySQL within seconds, the real-time CDC pipeline is working correctly and you can proceed with application cutover at your own pace with both databases fully in sync throughout the process.
Supported Platforms
| Platform | Connector to Use |
|---|---|
| Self-hosted MariaDB | MariaDB connector |
| Azure Database for MariaDB | MariaDB connector with SSH tunnel or IP allowlist |
| Amazon RDS for MariaDB | Amazon RDS for MariaDB connector |
Post-Migration Verification
A successful import does not mean a successful migration. These checks verify that data, schema, and application behavior are correct before you cut production traffic over to MySQL.
Row Count Verification
The fastest sanity check. Run this on both databases and compare results for every migrated table:
plaintext language-sqlSELECT
table_name,
table_rows
FROM information_schema.tables
WHERE table_schema = 'your_database'
ORDER BY table_name;
Note that table_rows in information_schema is an estimate for InnoDB tables. For exact counts on tables where the numbers do not match, run SELECT COUNT(*) FROM table_name directly on both sides.
Schema Verification
Verify that column definitions, data types, and constraints migrated correctly:
plaintext language-sqlSELECT
table_name,
column_name,
data_type,
character_set_name,
collation_name,
is_nullable,
column_default
FROM information_schema.columns
WHERE table_schema = 'your_database'
ORDER BY table_name, ordinal_position;
Run this on both MariaDB and MySQL and diff the output. Any differences in data_type, character_set_name, or collation_name need investigation before cutover.
Index Verification
Missing indexes after migration cause query performance degradation that may not be immediately obvious but becomes serious under production load:
plaintext language-sqlSELECT
table_name,
index_name,
column_name,
non_unique
FROM information_schema.statistics
WHERE table_schema = 'your_database'
ORDER BY table_name, index_name;
Compare the output between MariaDB and MySQL. Every index present in MariaDB should exist in MySQL with the same columns and uniqueness constraint.
Checksum Verification
For critical tables where exact data integrity must be confirmed, run a checksum comparison:
plaintext language-sql-- Run on both MariaDB and MySQL
CHECKSUM TABLE your_table;
Matching checksums confirm byte-level data integrity. Non-matching checksums on the same table indicate data differences that need investigation before cutover. Note that checksum results can differ legitimately if character set or collation changed during migration, even when the underlying data is semantically identical.
Application Query Testing
Schema and data verification confirm the database is correct. Application query testing confirms your application will behave correctly against MySQL. Before cutting over, run your application's test suite against the MySQL instance with production-equivalent data.
Pay specific attention to:
- Queries that use
ORDER BYon string columns, as collation differences between MariaDB and MySQL can change sort order - Stored procedures and functions that use MariaDB-specific syntax
- Any queries that rely on implicit type casting, which behaves differently between MariaDB and MySQL in edge cases
- Authentication, since MySQL 8.0's default
caching_sha2_passwordplugin may require client library updates
Troubleshooting Common MariaDB to MySQL Migration Errors
ERROR 1064: SQL Syntax Error on Import
Cause: The dump file contains MariaDB-specific syntax MySQL does not recognize. Most commonly NO_AUTO_CREATE_USER in sql_mode, MariaDB conditional comments starting with /*!M, or SEQUENCE object definitions.
Fix: Run the sed cleanup commands from Method 1 Step 2 against your dump file before importing. If errors persist, open the dump file and search for the specific line number in the error message to identify the exact syntax causing the failure.
ERROR 1273: Unknown Collation
Cause: The dump references a collation that exists in MariaDB but not in the target MySQL version. Common examples are utf8mb4_unicode_nopad_ci and utf8mb3_general_ci.
Fix:
plaintext language-bashsed -i 's/utf8mb4_unicode_nopad_ci/utf8mb4_unicode_ci/g' mariadb_dump.sql
sed -i 's/utf8mb3_general_ci/utf8mb4_general_ci/g' mariadb_dump.sql
ERROR 1231: Variable Cannot Be Set to This Value
Cause: The dump sets sql_mode values that MySQL does not support. MariaDB's sql_mode includes values like NO_AUTO_CREATE_USER that were removed from MySQL 8.0.
Fix:
plaintext language-bashsed -i 's/NO_AUTO_CREATE_USER//' mariadb_dump.sql
Estuary Capture Fails with Binlog Error
Cause: Either binlog_format is not set to ROW, binary log retention is too short, or the capture user is missing replication privileges.
Fix: Verify all three:
plaintext language-sqlSHOW VARIABLES LIKE 'binlog_format';
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
SHOW GRANTS FOR 'estuary_capture'@'%';
Correct any misconfigurations using the commands in Method 3 prerequisites and restart the capture in Estuary.
Authentication Errors After Migration
Cause: MySQL 8.0 defaults to caching_sha2_password but migrated user accounts or older application client libraries expect mysql_native_password.
Fix:
plaintext language-sqlALTER USER 'your_app_user'@'%'
IDENTIFIED WITH mysql_native_password
BY 'your_password';
FLUSH PRIVILEGES;
For MySQL 8.4 and later where mysql_native_password is removed, update your application's MySQL client library to a version that supports caching_sha2_password.
Data Truncation on DATETIME Columns
Cause: MariaDB and MySQL handle DATETIME values with fractional seconds differently when the column precision is not explicitly defined. Values with microseconds get silently truncated on import.
Fix: Before migration, check for DATETIME columns without explicit precision:
plaintext language-sqlSELECT table_name, column_name, datetime_precision
FROM information_schema.columns
WHERE table_schema = 'your_database'
AND data_type IN ('datetime', 'timestamp')
AND datetime_precision = 0;
For columns storing fractional seconds, alter them to DATETIME(6) before exporting.
Conclusion
Most MariaDB to MySQL migrations fail not because the tools are wrong but because the compatibility audit was skipped. The databases look similar enough that engineers assume they are interchangeable, start with a mysqldump, and discover three hours into the import that the database has Sequences, or INET6 columns, or stored procedures using MariaDB-only syntax. The pre-migration checklist in this guide exists specifically to prevent that outcome.
For the migration itself the right method depends on one question: can you afford downtime?
If yes, mysqldump is the fastest path for small to medium databases with no compatibility blockers. MySQL Workbench Migration Wizard adds schema inspection and visual editing for teams that want help resolving compatibility issues before data moves.
If no, Estuary is the only method in this guide that keeps MariaDB and MySQL in sync continuously, giving you a live parallel run period of days or weeks to validate everything before cutting over. It also handles the ongoing sync use case where both databases need to stay in sync permanently, which neither mysqldump nor the Migration Wizard can do.
The database migration itself is the easy part. The confidence to cut over production traffic is what takes time to build. Running both databases in sync simultaneously until that confidence exists is how teams avoid the midnight rollback.
Start syncing MariaDB to MySQL in real time
Estuary connects to your MariaDB instance using binary log CDC, captures every change as it happens, and keeps your MySQL instance in sync continuously. Supports self-hosted MariaDB, Azure Database for MariaDB, and Amazon RDS for MariaDB.
Setup takes under 30 minutes. Your first pipeline is free.
Start building at dashboard.estuary.dev.
Further Reading:
- MariaDB Connector Documentation for full prerequisites and configuration
- MySQL Materialization Connector for MySQL destination setup
- Change Data Capture Guide for a deeper reference on CDC concepts and binary log capture
FAQs
Can I migrate MariaDB to MySQL without downtime?
Which version of MySQL should I migrate to from MariaDB?
Does Estuary support Amazon RDS for MariaDB?

About the author
With over 15 years in data engineering, a seasoned expert in driving growth for early-stage data companies, focusing on strategies that attract customers and users. Extensive writing provides insights to help companies scale efficiently and effectively in an evolving data landscape.
















