to participate in how MariaDB-based systems are defined and adopted. Supporting the Foundation complements investment in MariaDB by: • strengthening the ecosystem in which MariaDB is used • improving how technologies are positioned within real architectures • increasing visibility at the point of infrastructure decision Support also ensures: • long-term openness and continuity of MariaDB Server • independent governance and freedom from lock-in Copyright @ 2026 MariaDB Foundation. 8
• Lower licensing and vendor lock-in pressure • More flexibility for self-managed, hybrid, or cloud deployments • Open-source governance and community-driven ecosystem • Opportunity to modernize operations during the move Technical drivers • Strong support for SQL standards and protocol compatibility for many MySQL-based apps • Mature replication, backup, and HA options • MariaDB-specific features for teams that want to evolve beyond a strict MySQL footprint • No roadmap The important mindset shift Older releases of MariaDB were often treated as a near drop-in replacement. For modern estates, especially since MySQL 8.x, plan as an application-compatible migration, not a blind binary swap. Migration projects succeed when teams explicitly test SQL behavior, authentication, connectors, replication mode, and performance baselines before cutover. Copyright @ 2026 MariaDB Foundation. 12
long-term viability Oracle's focus is only OCI and HeatWave, not MySQL • OCI & HeatWave Innovations • Innovation releases without real or limited innovation Almost empty LTS • MySQL 8.4 (first major release in 6 years) • 3 major new features: ◦ automatic histogram updates ◦ tagged GTIDs ◦ dedicated FLUSH_PRIVILEGES Decline of Community Engagement • decrease of bug fixes • decrease of contribution processing • state of connectors Copyright @ 2026 MariaDB Foundation. 13
• MySQL as a Global Unit • "Make MySQL a better MySQL" • Four major releases, 5.5, 5.6, 5.7 and 8.0 2 Diverted & Disassembled (2019-2024) • Engineering diverted to OCI MySQL DBaaS • Engineering further diverted to HeatWave • Loss of key leadership, end of Global Business Unit • One LTS release (8.4) and some innovation releases very limited 3 A Foretold End (2025-2026) • Huge layoffs, including MySQL leadership, MySQL engineering teams • No more sales or marketing support for MySQL • Some development units are without engineers • One last attempt before another round of mass layoffs Copyright @ 2026 MariaDB Foundation. 14
Feature(s) MySQL 8.1 2023-07-18 Capturing EXPLAIN FORMAT=JSON output MySQL 8.2 2023-10-25 MySQL 8.3 2024-01-16 MySQL 9.0 2024-07-23 - VECTOR datatype (no distance) - JavaScript Stored Procedure MySQL 9.1 2024-10-15 OpenTelemetry MySQL 9.2 2025-01-21 Group Replication enhancements MySQL 9.3 2025-04-15 MySQL 9.4 2025-07-22 - JSON duality views - Updateable JSON duality views MySQL 9.5 2025-10-21 MySQL 9.6 2026-01-20 container_aware flag Enterprise Edition only feature Copyright @ 2026 MariaDB Foundation. 16
to revert many bad decisions but creating more confusion and uncertainty in the process. Oracle, tried to re-engage with the Community, but the message is redundant, unclear and not credible, especially after the layoffs and the lack of real innovation in the last 3 years. To save time, many Enterprise Edition dedicated features will be open-sourced within the next LTS release, but that will not save MySQL from its decline, as the core issues are not only about features but about the lack of a clear roadmap, the lack of innovation, and the lack of support for the Community. The willing of the remaining team is there... but they will lack the resources and a roadmap! Copyright @ 2026 MariaDB Foundation. 17
9.x, the gap between MySQL and MariaDB Server has widened, especially in terms of SQL behavior, authentication, and replication modes. Key differences to consider • SQL dialect differences (functions, JSON handling, optimizer behavior) • Authentication and user management changes • Replication incompatibilities (GTIDs, replication modes) InnoDB is no longer fully compatible • MariaDB uses a forked version of InnoDB evolving separately • MySQL introduces changes that break compatibility (e.g., redo log format, undo logs) • and MariaDB did other changes also breaking that compatibility Copyright @ 2026 MariaDB Foundation. 20
as storage engines, size, routines, events, users, plugins, topology and application dependencies 2 Assess Compatibility check authentication plugins, SQL modes, reserved keywords, JSON functions, GTIDs 3 Baseline establish performance baselines, identify critical queries, and measure current system metrics set the expectations 4 Test Migration perform test migrations, validate data integrity, and test application compatibility Iterate and refine 5 Plan Cutover develop a detailed cutover plan, including rollback procedures, and communication plan Copyright @ 2026 MariaDB Foundation. 21
as storage engines, size, routines, events, users, plugins, topology and application dependencies 2 Assess Compatibility check authentication plugins, SQL modes, reserved keywords, JSON functions, GTIDs 3 Baseline establish performance baselines, identify critical queries, and measure current system metrics set the expectations 4 Test Migration perform test migrations, validate data integrity, and test application compatibility Iterate and refine 5 Plan Cutover develop a detailed cutover plan, including rollback procedures, and communication plan Do not start with data movement. Start with evidence: exact information, incompatibilities, and performance baselines. This will guide your migration strategy and help set realistic expectations, and a tested rollback path. Copyright @ 2026 MariaDB Foundation. 21
as storage engines, size, routines, events, users, plugins, topology and application dependencies 2 Assess Compatibility check authentication plugins, SQL modes, reserved keywords, JSON functions, GTIDs 3 Baseline establish performance baselines, identify critical queries, and measure current system metrics set the expectations 4 Test Migration perform test migrations, validate data integrity, and test application compatibility Iterate and refine 5 Plan Cutover develop a detailed cutover plan, including rollback procedures, and communication plan Do not start with data movement. Start with evidence: exact information, incompatibilities, and performance baselines. This will guide your migration strategy and help set realistic expectations, and a tested rollback path. No matter what pain arises, it would be much worse during a migration to PostgreSQL Copyright @ 2026 MariaDB Foundation. 21
in use across environments • Storage engines used (InnoDB, MyISAM, etc.) • Database size and growth patterns • Routines, events, and triggers in use • User accounts and authentication plugins • Replication topology and GTID usage • Application dependencies and compatibility requirements Copyright @ 2026 MariaDB Foundation. 23
DATA, sys.format_bytes(sum(index_length)) INDEXES, sys.format_bytes(sum(data_length + index_length)) 'TOTAL SIZE', engine `ENGINE` FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') GROUP BY engine; Copyright @ 2026 MariaDB Foundation. 25
the size of the data directory: du du -sh -sh /var/lib/mysql /var/lib/mysql [ [root@mucha ~ root@mucha ~] ]# du -sh database/ # du -sh database/ 148G database/ 148G database/ Copyright @ 2026 MariaDB Foundation. 26
running the following query: MySQL > SELECT sys.format_bytes(sum(data_length)) DATA, sys.format_bytes(sum(index_length)) INDEXES, sys.format_bytes(sum(data_length + index_length)) 'TOTAL SIZE' FROM information_schema.TABLES ORDER BY data_length + index_length; Copyright @ 2026 MariaDB Foundation. 27
FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY ROUTINE_SCHEMA, ROUTINE_TYPE, ROUTINE_NAME; Copyright @ 2026 MariaDB Foundation. 30
FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY ROUTINE_SCHEMA, ROUTINE_TYPE, ROUTINE_NAME; Empty set (0.04 sec) Copyright @ 2026 MariaDB Foundation. 30
EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY TRIGGER_SCHEMA, EVENT_OBJECT_TABLE, TRIGGER_NAME; Copyright @ 2026 MariaDB Foundation. 31
EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY TRIGGER_SCHEMA, EVENT_OBJECT_TABLE, TRIGGER_NAME; Empty set (0.01 sec) Copyright @ 2026 MariaDB Foundation. 31
STATUS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY EVENT_SCHEMA, EVENT_NAME; Copyright @ 2026 MariaDB Foundation. 32
STATUS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY EVENT_SCHEMA, EVENT_NAME; Empty set (0.00 sec) Copyright @ 2026 MariaDB Foundation. 32
db_name, ROUTINE_NAME AS object_name, ROUTINE_TYPE AS extra FROM INFORMATION_SCHEMA.ROUTINES UNION ALL SELECT 'TRIGGER', TRIGGER_SCHEMA, TRIGGER_NAME, CONCAT(ACTION_TIMING, ' ', EVENT_MANIPULATION, ' ON ', EVENT_OBJECT_TABLE) FROM INFORMATION_SCHEMA.TRIGGERS UNION ALL SELECT 'EVENT', EVENT_SCHEMA, EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS ORDER BY db_name, object_kind, object_name; summary all at once Copyright @ 2026 MariaDB Foundation. 33
and by how many users? MySQL > select plugin, count(*) users from mysql.user group by plugin; +-----------------------+-------+ | plugin | users | +-----------------------+-------+ | mysql_native_password | 14 | | caching_sha2_password | 9 | +-----------------------+-------+ 2 rows in set (0.00 sec) Copyright @ 2026 MariaDB Foundation. 36
m_u.host FROM mysql.user m_u LEFT JOIN performance_schema.accounts ps_a ON m_u.user = ps_a.user AND ps_a.host = m_u.host LEFT JOIN information_schema.views is_v ON is_v.DEFINER = CONCAT(m_u.User, '@', m_u.Host) AND is_v.security_type = 'DEFINER' LEFT JOIN information_schema.routines is_r ON is_r.DEFINER = CONCAT(m_u.User, '@', m_u.Host) AND is_r.security_type = 'DEFINER' LEFT JOIN information_schema.events is_e ON is_e.definer = CONCAT(m_u.user, '@', m_u.host) LEFT JOIN information_schema.triggers is_t ON is_t.definer = CONCAT(m_u.user, '@', m_u.host) WHERE ps_a.user IS NULL AND is_v.definer IS NULL AND is_r.definer IS NULL AND is_e.definer IS NULL AND is_t.definer IS NULL ORDER BY m_u.user, m_u.host; Copyright @ 2026 MariaDB Foundation. 37
m_u.host FROM mysql.user m_u LEFT JOIN performance_schema.accounts ps_a ON m_u.user = ps_a.user AND ps_a.host = m_u.host LEFT JOIN information_schema.views is_v ON is_v.DEFINER = CONCAT(m_u.User, '@', m_u.Host) AND is_v.security_type = 'DEFINER' LEFT JOIN information_schema.routines is_r ON is_r.DEFINER = CONCAT(m_u.User, '@', m_u.Host) AND is_r.security_type = 'DEFINER' LEFT JOIN information_schema.events is_e ON is_e.definer = CONCAT(m_u.user, '@', m_u.host) LEFT JOIN information_schema.triggers is_t ON is_t.definer = CONCAT(m_u.user, '@', m_u.host) WHERE ps_a.user IS NULL AND is_v.definer IS NULL AND is_r.definer IS NULL AND is_e.definer IS NULL AND is_t.definer IS NULL ORDER BY m_u.user, m_u.host; Copyright @ 2026 MariaDB Foundation. +------------------+-----------+ | user | host | +------------------+-----------+ | mysql.infoschema | localhost | | mysql.session | localhost | | wp_lefred | 127.0.0.1 | +------------------+-----------+ 37
special-role/ global-role features, and system tables are different enough that some role scripts are not automatically portable between MySQL and MariaDB. Listing the roles: MySQL > SELECT distinct DISTINCT User 'Role Name', if(from_user is NULL,0, 1) Active FROM mysql.user LEFT JOIN role_edges ON from_user=user WHERE account_locked='Y' AND password_expired='Y' AND authentication_string=''; +-----------+--------+ | Role Name | Active | +-----------+--------+ | wp_reader | 0 | +-----------+--------+ 1 row in set (0.0023 sec) Copyright @ 2026 MariaDB Foundation. 38
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | gtid_mode | OFF | +---------------+-------+ MySQL > show global variables like 'gtid_mode'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | gtid_mode | ON | +---------------+-------+ MySQL > show global variables like 'enforce_gtid_consistency'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | enforce_gtid_consistency | ON | +--------------------------+-------+ Copyright @ 2026 MariaDB Foundation. 39
inventory of your replication topology: # ./pt-replica-find -u clusteradmin -h mysql1 --password "Passw0rd!" mysql1 Version 8.4.8 Server ID 410232619 Uptime 45:29 (started 2026-04-20T14:28:26) Replication Is not a replica, has 2 replicas connected, is not read_only Filters Binary logging ROW Slave status Slave mode STRICT Auto-increment increment 1, offset 1 InnoDB version 8.4.8 +- mysql3 Version 8.4.3 Server ID 3078509641 Uptime 34:39 (started 2026-04-20T14:39:16) Replication Is a replica, has 0 replicas connected, is read_only Filters Binary logging ROW Slave status 0 seconds behind, running, no errors Slave mode STRICT Auto-increment increment 1, offset 1 InnoDB version 8.4.3 +- mysql2 Version 8.4.0 Server ID 3957045113 Uptime 42:08 (started 2026-04-20T14:31:47) Replication Is a replica, has 0 replicas connected, is read_only Filters Binary logging ROW Slave status 0 seconds behind, running, no errors Slave mode STRICT Auto-increment increment 1, offset 1 InnoDB version 8.4.0 Copyright @ 2026 MariaDB Foundation. 40
can change how the database interprets SQL queries, handles data validation, and even enforces certain standards. MySQL > select @@sql_mode\G Copyright @ 2026 MariaDB Foundation. 42
can change how the database interprets SQL queries, handles data validation, and even enforces certain standards. MySQL > select @@sql_mode\G *************************** 1. row *************************** @@sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE, NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION 1 row in set (0.0012 sec) Copyright @ 2026 MariaDB Foundation. 42
ORACLE No Yes MariaDB compatibility mode POSTGRESQL No Yes MariaDB compatibility mode SIMULTANEOUS_ASSIGNMENT No Yes MariaDB-only TIME_ROUND_FRACTIONAL No Yes MariaDB-only ANSI Yes Yes Exists in both, but composition differs TRADITIONAL Yes Yes Exists in both, but composition differs Copyright @ 2026 MariaDB Foundation. 44
default ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION STRICT_TRANS_TABLES, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION Stricter GROUP BY by default Yes (`ONLY_FULL_GROUP_BY`) No Zero-date checks by default Yes (`NO_ZERO_IN_DATE`, `NO_ZERO_DATE`) No Strict mode enabled by default Yes (`STRICT_TRANS_TABLES`) Yes (`STRICT_TRANS_TABLES`) Division by zero mode enabled by default Yes Yes Engine substitution disabled by default Yes (`NO_ENGINE_SUBSTITUTION`) Yes (`NO_ENGINE_SUBSTITUTION`) Includes `NO_AUTO_CREATE_USER` by default No (Not a mode in MySQL, it's the only behavior) Yes Copyright @ 2026 MariaDB Foundation. 45
aspect of MySQL's and MariaDB's behavior that affects how the database handles invalid or out-of-range data during data modification operations (INSERT, UPDATE, etc.). When this mode is enabled, the database will reject any operation that attempts to insert or update data that violates data type constraints, such as inserting a string into an integer column or inserting a value that exceeds the defined range for a column. Instead of silently truncating or adjusting the data, the operation will fail with an error, ensuring data integrity and preventing unintended consequences. Copyright @ 2026 MariaDB Foundation. 46
has gone through multiple versions and updates, the definition of temporal fields can often be problematic. mysql> SELECT table_schema, table_name, column_name, column_type, column_default FROM information_schema.columns WHERE column_default IN ('0000-00-00', '0000-00-00 00:00:00') AND table_schema NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY table_name, ordinal_position; Copyright @ 2026 MariaDB Foundation. 47
has gone through multiple versions and updates, the definition of temporal fields can often be problematic. mysql> SELECT table_schema, table_name, column_name, column_type, column_default FROM information_schema.columns WHERE column_default IN ('0000-00-00', '0000-00-00 00:00:00') AND table_schema NOT IN ('sys','mysql', 'information_schema', 'performance_schema', 'mysql_innodb_cluster_metadata') ORDER BY table_name, ordinal_position; We do have 47 columns defined with such default! Copyright @ 2026 MariaDB Foundation. 47
Yes (default) Yes (but needs to be enabled manually) MySQL default since 8.0 mysql_native_password Disabled by default (deprecated) Yes (default) Removed in MySQL 9.0 mysql_old_password No Yes pre MySQL 4.1 sha256_password Yes No MySQL-only, older alternative to caching_sha2_password auth_socket Yes Yes Unix socket auth; MariaDB commonly uses unix_socket unix_socket No Yes MariaDB equivalent naming for socket-based auth ed25519 No Yes MariaDB-only modern password authentication plugin pam No Yes MariaDB PAM authentication Copyright @ 2026 MariaDB Foundation. 48
gssapi No Yes MariaDB Kerberos/GSSAPI authentication ldap_simple No Yes MariaDB LDAP simple authentication ldap_sasl No Yes MariaDB LDAP SASL authentication dialog Yes Yes Interactive authentication plugin mysql_clear_password Yes Yes Sends password in cleartext; use with TLS authentication_kerberos Yes No MySQL Kerberos plugin authentication_ldap_sasl Yes No MySQL LDAP SASL plugin authentication_ldap_simple Yes No MySQL LDAP simple plugin authentication_windows Yes No MySQL Windows native authentication auth_pam_compat No Yes MariaDB PAM compatibility plugin Copyright @ 2026 MariaDB Foundation. 49
applications rely on MySQL's X Protocol for document store access or other features, you will need to modify them to work with standard SQL in MariaDB. You can verify if X Protocol is in use by checking the related satus variables Copyright @ 2026 MariaDB Foundation. 50
'Mysqlx_sessions_accepted' THEN VARIABLE_VALUE END) AS sessions_accepted, MAX(CASE WHEN VARIABLE_NAME = 'Mysqlx_sessions_closed' THEN VARIABLE_VALUE END) AS sessions_closed, MAX(CASE WHEN VARIABLE_NAME = 'Mysqlx_connections_accepted' THEN VARIABLE_VALUE END) AS conns_accepted, MAX(CASE WHEN VARIABLE_NAME = 'Mysqlx_connections_closed' THEN VARIABLE_VALUE END) AS conns_closed FROM performance_schema.global_status WHERE VARIABLE_NAME IN ( 'Mysqlx_sessions_accepted', 'Mysqlx_sessions_closed', 'Mysqlx_connections_accepted', 'Mysqlx_connections_closed' ); Copyright @ 2026 MariaDB Foundation. 51
'Mysqlx_sessions_accepted' THEN VARIABLE_VALUE END) AS sessions_accepted, MAX(CASE WHEN VARIABLE_NAME = 'Mysqlx_sessions_closed' THEN VARIABLE_VALUE END) AS sessions_closed, MAX(CASE WHEN VARIABLE_NAME = 'Mysqlx_connections_accepted' THEN VARIABLE_VALUE END) AS conns_accepted, MAX(CASE WHEN VARIABLE_NAME = 'Mysqlx_connections_closed' THEN VARIABLE_VALUE END) AS conns_closed FROM performance_schema.global_status WHERE VARIABLE_NAME IN ( 'Mysqlx_sessions_accepted', 'Mysqlx_sessions_closed', 'Mysqlx_connections_accepted', 'Mysqlx_connections_closed' ); +-------------------+-----------------+----------------+--------------+ | sessions_accepted | sessions_closed | conns_accepted | conns_closed | +-------------------+-----------------+----------------+--------------+ | 1769 | 0 | 1783 | 1783 | +-------------------+-----------------+----------------+--------------+ 1 row in set (0.01 sec) Copyright @ 2026 MariaDB Foundation. 51
the presence of MySQL's NoSQL document store collections: MySQL > SELECT c.TABLE_SCHEMA, c.TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS AS c JOIN INFORMATION_SCHEMA.TABLES AS t ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.TABLE_NAME = c.TABLE_NAME WHERE t.TABLE_TYPE = 'BASE TABLE' AND c.COLUMN_NAME = 'doc' AND c.DATA_TYPE = 'json' AND c.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') ORDER BY c.TABLE_SCHEMA, c.TABLE_NAME; Copyright @ 2026 MariaDB Foundation. 52
the presence of MySQL's NoSQL document store collections: MySQL > SELECT c.TABLE_SCHEMA, c.TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS AS c JOIN INFORMATION_SCHEMA.TABLES AS t ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.TABLE_NAME = c.TABLE_NAME WHERE t.TABLE_TYPE = 'BASE TABLE' AND c.COLUMN_NAME = 'doc' AND c.DATA_TYPE = 'json' AND c.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') ORDER BY c.TABLE_SCHEMA, c.TABLE_NAME; Copyright @ 2026 MariaDB Foundation. +--------------+------------+ | TABLE_SCHEMA | TABLE_NAME | +--------------+------------+ | library | books | | vinyl | records | +--------------+------------+ 2 rows in set (0.04 sec) 52
JSON data type Native JSON type JSON is an alias for LONGTEXT COLLATE utf8mb4_bin Storage format, validation, replication, and migration behavior differ. Internal storage Stored in MySQL's native binary JSON format Stored as text MySQL optimizes JSON storage/ access differently; MariaDB keeps JSON as textual data. Validation on insert Invalid JSON in a JSON column raises an error Validation is enforced through the JSON alias / JSON_VALID check behavior Data-cleanliness rules look similar at SQL level, but implementation differs. Replication / migration Native JSON columns are normal MariaDB recommends converting MySQL JSON to TEXT/LONGTEXT, using statement-based replication, or using the mysql_json plugin during migration Direct cross-engine migration of JSON columns can break or need conversion. JSON_TABLE() Supported Supported Both can project JSON into relational rows. Copyright @ 2026 MariaDB Foundation. 53
matters Schema validation functions Supports JSON schema validation functions such as JSON_SCHEMA_VALID() Supported Schema-based JSON validation is similar. Normalization helpers No direct equivalent documented like MariaDB's JSON_NORMALIZE() Supports JSON_NORMALIZE() MariaDB has built-in canonicalization for equality/ unique-comparison workflows. Pretty / loose formatting helpers Supports JSON_PRETTY() only Supports JSON_LOOSE() and JSON_DETAILED() / JSON_PRETTY() MariaDB has more formatting- oriented helper functions. JSON_VALUE() Supported as part of MySQL's JSON function set Supported Scalar extraction exists in both, but surrounding JSON ecosystem differs. JSON_EXTRACT() Supported Supported Core path extraction is broadly compatible. Copyright @ 2026 MariaDB Foundation. 54
matters JSON_SET(), JSON_REPLACE(), JSON_SEARCH() Supported Supported Many day-to-day JSON manipulation functions overlap. Aggregate JSON functions JSON_ARRAYAGG(), JSON_OBJECTAGG() supported JSON_ARRAYAGG(), JSON_OBJECTAGG() supported Aggregation is available on both sides, though execution details may differ. Equality / canonical comparison No dedicated documented function like JSON_NORMALIZE() JSON_NORMALIZE() sorts keys and removes spaces MariaDB gives you a built-in path to compare semantically equivalent JSON documents. Compatibility direction Own native JSON implementation SQL-level compatibility with MySQL functions, but different storage model Queries may port more easily than storage or operational behavior. -> & ->> Supported Not supported yet These operators are used for JSON path extraction. Copyright @ 2026 MariaDB Foundation. 55
> SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS WHERE DATA_TYPE = 'json' AND TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys', 'mysql_innodb_cluster_metadata' ) ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION; Copyright @ 2026 MariaDB Foundation. 56
keywords. If your application uses any of these as identifiers (e.g., table names, column names) without quoting them, you may encounter syntax errors after migration. • MySQL counts 734 keywords • 259 keywords are reserved • MariaDB counts 699 keywords • it's not clear how many are reserved • it seems they are also 259 Copyright @ 2026 MariaDB Foundation. 60
create table accessible (id int); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'accessible (id int)' at line 1 MariaDB > create table accessible (id int); Query OK, 0 rows affected (0.037 sec) MySQL > create table conversion (id int); Query OK, 0 rows affected (0.03 sec) MariaDB > create table conversion (id int); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'conversion (id int)' at line 1 Copyright @ 2026 MariaDB Foundation. 66
some configuration variables that exist in one may not exist in the other. To facilitate migration, some removed settings in MariaDB have been aliased to no-op variables that can be set to the same values as in MySQL without causing errors, but they won't have any effect. Copyright @ 2026 MariaDB Foundation. 67
some configuration variables that exist in one may not exist in the other. To facilitate migration, some removed settings in MariaDB have been aliased to no-op variables that can be set to the same values as in MySQL without causing errors, but they won't have any effect. For example innodb_thread_concurrency is a no-op variable and will create a warning in the error log if set, but it won't cause an error and won't affect performance: Apr 28 11:27:09 dell mariadbd[3811998]: 2026-04-28 11:27:09 0 [Warning] 'innodb-thread-concurrency' was removed. It does nothing now and exists only for compatibility with old my.cnf files. Copyright @ 2026 MariaDB Foundation. 67
your MySQL configuration file before migration and remove or comment out any settings that are no longer relevant in MariaDB. It's also very important to review all messages and warnings in the MariaDB error log during the migration, as they may indicate configuration settings that need to be adjusted or removed. Copyright @ 2026 MariaDB Foundation. 68
your MySQL configuration file before migration and remove or comment out any settings that are no longer relevant in MariaDB. It's also very important to review all messages and warnings in the MariaDB error log during the migration, as they may indicate configuration settings that need to be adjusted or removed. I have created a MDEV to track the no-op variables when they are set: https://jira.mariadb.org/browse/MDEV-39252 Copyright @ 2026 MariaDB Foundation. 68
Specialized Migration Scenarios Migrating to MariaDB from MySQL The documentation for migrating from MySQL to MariaDB is available at https:// mariadb.com/docs/server/server-management/install-and-upgrade-mariadb/ migrating-to-mariadb/moving-from-mysql Copyright @ 2026 MariaDB Foundation. 70
you would want to gather performance metrics on your MySQL system before migration. This includes: • Query performance (e.g., using EXPLAIN ANALYZE on critical queries) • Resource utilization (CPU, memory, disk I/O) • Replication lag (if applicable) • Application response times • Error rates and logs • User connection patterns and load profiles Copyright @ 2026 MariaDB Foundation. 72
a clear plan for your target for the new MariaDB environment. • What is the response time expectation? (same, 10% margin, etc.) • What is the acceptable replication lag (if applicable)? • What are the critical queries that must perform well? • What are the resource utilization targets? • What are the error rate thresholds? Copyright @ 2026 MariaDB Foundation. 73
a clear plan for your target for the new MariaDB environment. • What is the response time expectation? (same, 10% margin, etc.) • What is the acceptable replication lag (if applicable)? • What are the critical queries that must perform well? • What are the resource utilization targets? • What are the error rate thresholds? That's the only way to validate the migration Copyright @ 2026 MariaDB Foundation. 73
only valid way to migrate from MySQL to MariaDB, due to the differences in storage formats and features. You can use mysqldump or mydumper to export the data from MySQL, and then import it into MariaDB. Copyright @ 2026 MariaDB Foundation. 75
only valid way to migrate from MySQL to MariaDB, due to the differences in storage formats and features. You can use mysqldump or mydumper to export the data from MySQL, and then import it into MariaDB. If you use mydumper, I recommend to also use compression. $ mydumper --compact --user=admin --password=yourpass --exec-per-thread="/usr/bin/zstd -c" --exec-per-thread-extension=".zst" -v 3 Copyright @ 2026 MariaDB Foundation. 75
only valid way to migrate from MySQL to MariaDB, due to the differences in storage formats and features. You can use mysqldump or mydumper to export the data from MySQL, and then import it into MariaDB. If you use mydumper, I recommend to also use compression. $ mydumper --compact --user=admin --password=yourpass --exec-per-thread="/usr/bin/zstd -c" --exec-per-thread-extension=".zst" -v 3 ** (mydumper:11262): CRITICAL **: 08:43:13.099: Non transactional table found: `mysqlandfriends`.`wp_tz_plusgallery_item` on a consistent backup attempt. Restart backup using --trx-tables=0 to indicate that you have non transactional tables. Copyright @ 2026 MariaDB Foundation. 75
4 MyISAM tables! Now it's up to you to decide how to handle them. You can either convert them to InnoDB before migration, or you can migrate them as MyISAM but your backup won't be consistent, and you will need to use --trx-tables=0 with mydumper to ignore the transactional consistency check. Copyright @ 2026 MariaDB Foundation. 76
4 MyISAM tables! Now it's up to you to decide how to handle them. You can either convert them to InnoDB before migration, or you can migrate them as MyISAM but your backup won't be consistent, and you will need to use --trx-tables=0 with mydumper to ignore the transactional consistency check. If possible, I always recommend converting MyISAM tables to InnoDB!! Copyright @ 2026 MariaDB Foundation. 76
in consideration the findings we discovered during the inventory phase. In our case, we will ignore the sys schema table, and the two collections we found. So we create a file named exclude.txt with the following content: sys library.books vinyl.records Copyright @ 2026 MariaDB Foundation. 80
in consideration the findings we discovered during the inventory phase. In our case, we will ignore the sys schema table, and the two collections we found. So we create a file named exclude.txt with the following content: sys library.books vinyl.records If you use InnoDB Cluster or ReplicaSet ignore the metadata schema: mysql_innodb_cluster_metadata Copyright @ 2026 MariaDB Foundation. 80
the fact that older version of MySQL allowed 0000-00-00 00:00:00 as a default value for datetime columns, while new versions, and MariaDB does not (see SQL_MODE=STRICT_TRANS_TABLES). Copyright @ 2026 MariaDB Foundation. 82
the fact that older version of MySQL allowed 0000-00-00 00:00:00 as a default value for datetime columns, while new versions, and MariaDB does not (see SQL_MODE=STRICT_TRANS_TABLES). We have again several options to handle this: • Modify the dump file to remove the default value (not recommended) • Modify the table definition in MySQL and redo the dump • Modify the dump's metadata to change the SQL_MODE (faster) Copyright @ 2026 MariaDB Foundation. 82
minimal downtime, you can set up replication from MySQL to MariaDB. This allows you to see how your new MariaDB system performs under load, and validate your queries. Of course, if you ignored some schemas or tables during the initial dump and restore, you will need to handle that in the replication setup as well. Copyright @ 2026 MariaDB Foundation. 85
server to be a source for replication. We need to create a replication user, and grant it the necessary privileges: MySQL > CREATE USER 'repl'@'%' IDENTIFIED BY 'replpass'; MySQL > GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; We also need to confirm that the binary log is enabled (default) and that the server has a unique server_id: MySQL > select @@log_bin; +-----------+ | @@log_bin | +-----------+ | 1 | +-----------+ Copyright @ 2026 MariaDB Foundation. 86
If log_bin is off, you need to enable it and restart the MySQL server, by commenting the following line as binary logs are enabled by default in MySQL: [mysqld] #disable_log_bin And don't forget to be sure to have enough time to restore and prepare the replica, MySQL should not purge the binary logs before we start replication. select @@binlog_expire_logs_seconds/60/60/24; +---------------------------------------+ | @@binlog_expire_logs_seconds/60/60/24 | +---------------------------------------+ | 30.000000000000 | +---------------------------------------+ Copyright @ 2026 MariaDB Foundation. 87
to prepare the server to be a replica of MySQL. [mariadb] server_id=2 slave_parallel_mode=conservative We also need to enable caching_sha2_password plugin: MariaDB > INSTALL SONAME 'auth_mysql_sha2'; Query OK, 0 rows affected (0.024 sec) Copyright @ 2026 MariaDB Foundation. 88
some schemas and tables, it's time to tell MariaDB to ignore them: MariaDB > SET GLOBAL replicate_ignore_table='library.books,vinyl.records'; MariaDB > SET GLOBAL replicate_ignore_db='sys,mysql_innodb_cluster_metadata'; And we can start replication: MariaDB > start replica; Query OK, 0 rows affected (0.028 sec) Copyright @ 2026 MariaDB Foundation. 90
is available in MariaDB, it only supports authentication, and not replication. This means you shouldn't create new users until the migration is complete. JSON columns must be converted to LONGTEXT prior to migration if replication and modification or insertion are required, since MariaDB does not support ROW based replication for the JSON data type: Last_SQL_Error: Table structure for binlog event is not compatible with the table definition on this slave: In RBR mode, Slave received unknown field type field 245 for column Name: fred.test_json.options Copyright @ 2026 MariaDB Foundation. 92
ms) MySQL 8.4.9 MySQL Community Server - GPL x86_64 Linux 1.3.2 (Ok, 31 ms) MySQL 12.3.1-MariaDB-log MariaDB Server x86_64 Linux system 21a047800091 OpenSSL 3.5.1 1 Jul 2025 (Ok, 17 ms) Reading the database schema (349 tables, 0 objects, 97 ms) Validating table row count (4 concurrent sessions): cards.proposed - Started (1 of 349, session 1) cards.proposed - Ok (4 ms, session 1) Source: 37 rows (4 ms) Target: 37 rows (1 ms) ... 112. wp_lefred.wp_commentmeta (Source rows: 36342, Target rows: 36342) 113. rss.ttrss_entries (Source rows: 83339, Target rows: 83339) Summary: Total number of tables: 349 With the same row count: 349 With the different row count: 0 Total number of rows: 884498 in source, 884498 in target Row count difference: 0 Copyright @ 2026 MariaDB Foundation. 94
that everything is working as expected is to let run the replica for a while, and then compare the data on both sides. Also verify that the replication doesn't break, and that the replica is not lagging behind. You can also perform a data integrity check using tools like pt-table-checksum from Percona Toolkit, which can compare the data between the source and replica and report any discrepancies. Copyright @ 2026 MariaDB Foundation. 96
a user that uses the mysql_native_password plugin, as pt- table-checksum does not support caching_sha2_password yet. MySQL > CREATE USER 'checksum'@'%' IDENTIFIED WITH mysql_native_password BY 'passwd'; MySQL > GRANT SELECT ON *.* TO 'checksum'@'%'; Copyright @ 2026 MariaDB Foundation. 97
a user that uses the mysql_native_password plugin, as pt- table-checksum does not support caching_sha2_password yet. MySQL > CREATE USER 'checksum'@'%' IDENTIFIED WITH mysql_native_password BY 'passwd'; MySQL > GRANT SELECT ON *.* TO 'checksum'@'%'; # ./pt-table-checksum --user checksum --password passwd --host=192.168.56.2 --no-check-binlog-format --nocheck-replication-filters --ignore-databases=mysql,sys,mysql_innodb_cluster_metadata -q 2>/dev/null Checking if all tables can be checksummed ... Starting checksum ... TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE 04-21T14:48:43 1 0 0 0 0 0 0.002 library.books 04-21T14:49:00 1 0 0 0 0 0 0.001 vinyl.records Copyright @ 2026 MariaDB Foundation. 97
mismatch to see how the tool reports it: MariaDB > select db, tbl, this_crc, this_cnt, source_crc, source_cnt from percona.checksums where this_crc <> source_crc; Empty set (0.000 sec) Copyright @ 2026 MariaDB Foundation. 98
mismatch to see how the tool reports it: MariaDB > select db, tbl, this_crc, this_cnt, source_crc, source_cnt from percona.checksums where this_crc <> source_crc; Empty set (0.000 sec) MariaDB > select id, title from ttrss_entries limit 2; +------+------------------------------------------------------------+ | id | title | +------+------------------------------------------------------------+ | 6588 | mariadb 10.6 laravel migration | | 6848 | Encoding not responding [closed] | +------+------------------------------------------------------------+ MariaDB > update ttrss_entries set title = "Encoding never responding [closed]" where id =6848; Copyright @ 2026 MariaDB Foundation. 98
important to test the application against the new MariaDB database to ensure that everything is working as expected. This includes testing all critical queries, stored procedures, and application features that interact with the database. You also need to monitor the response times and error rates to ensure that the application performs well with MariaDB. And finally, you need to monitor the resource utilization on the new system. Copyright @ 2026 MariaDB Foundation. 100
outlines the steps to be taken during the final migration from MySQL to MariaDB. The cutover plan should include: 1 A timeline of the cutover process 2 A list of tasks to be performed during the cutover 3 A list of responsible parties for each task 4 A communication plan to inform stakeholders of the cutover process and any expected downtime 5 A rollback plan in case of any issues during the cutover MySQL cannot be configured as replica of MariaDB using ROW based replication! Copyright @ 2026 MariaDB Foundation. 102
cutover, we need to have a rollback plan in case anything goes wrong. At that time, before promoting the MariaDB replica to be the new primary, we need to make some temporary changes in the configuration that should stay active until we validate the migration in production: [mariadb] log_bin=binlog server_id=2 slave_parallel_mode=conservative encrypt-binlog=0 log-bin-compress=0 character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci character_set_collations=utf8mb4=utf8mb4_unicode_ci gtid-strict-mode=OFF binlog_annotate_row_events=OFF binlog_format=STATEMENT Copyright @ 2026 MariaDB Foundation. 103
as a replica of our new promoted MariaDB. We need to create a replication user on the MariaDB side, and grant it the necessary privileges: MariaDB > CREATE USER 'repl'@'%' IDENTIFIED BY 'replpass'; MariaDB > GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; Copyright @ 2026 MariaDB Foundation. 104
the binary log file and position on the MariaDB side, and then configure MySQL to be a replica of MariaDB: MariaDB > show master status\G *************************** 1. row *************************** File: binlog.000003 Position: 1733 Binlog_Do_DB: Binlog_Ignore_DB: Gtid_Binlog_Pos: 0-2-19 Copyright @ 2026 MariaDB Foundation. 105