Chapter 02 · MariaDB vs MySQL: Compatibility, Divergence, and Migration Awareness

Shared Heritage vs Independent Evolution: Why Syntax Compatibility Is Not Feature Parity

Build a layered MariaDB/MySQL compatibility model that separates protocol, syntax, semantics, metadata, tools, replication, and performance—and verify each layer with evidence.

Intermediate90–115 minutesCompatibility matrix + executable probesMariaDB 12.3.2 baselineMySQL 8.4.11 comparisonLast reviewed: August 2026

Learning outcomes

ServiceHub has a working MariaDB 12.3 lab from Chapter 01. A developer now proposes moving an older MySQL-backed service by changing only the connection hostname because “MariaDB speaks MySQL.” The application does connect, simple SELECT statements work, and the team concludes the migration is finished. That conclusion confuses one successful compatibility layer with the entire database contract.

MariaDB and MySQL share ancestry, a large SQL vocabulary, familiar client protocols, and many ecosystem conventions. They have also evolved independently for years. Compatibility therefore has multiple dimensions: network protocol, authentication, SQL grammar, SQL semantics, metadata, storage engines, configuration, operational utilities, binary logging, replication, optimizer behavior, and performance. This lesson replaces a yes/no compatibility label with an evidence matrix.

01

Explain why shared MariaDB/MySQL heritage creates useful compatibility without guaranteeing feature parity.

02

Separate protocol compatibility from SQL syntax, semantics, metadata, configuration, tools, replication, and performance compatibility.

03

Collect server-side evidence that identifies the exact MariaDB or MySQL endpoint actually reached.

04

Build a compatibility matrix from executable probes instead of relying on “drop-in replacement” language.

05

Diagnose the mistake of treating a successful connection or smoke query as proof of migration readiness.

Chapter 01 continuity

Reuse the disposable servicehub database, explicit InnoDB tables, utf8mb4 assumptions, least-privilege accounts, and recorded SQL mode from Chapter 01. If you did not keep that lab, recreate it from the Chapter 01 seed/reset scripts before running compatibility probes.

1. A compatibility claim must name the layer

At the protocol layer, MariaDB deliberately maintains a high degree of compatibility with MySQL client protocols and APIs. That is why many MySQL-capable connectors can establish a session with MariaDB. But the protocol only carries commands and results. It does not promise that the target server accepts every source statement, interprets every type identically, exposes the same system variables, chooses the same execution plan, or writes compatible replication events.

A useful mental model is a stack. The bottom of the stack is transport and authentication: can the client reach a server and authenticate? Above that is parser compatibility: does the SQL text parse? Above parsing is semantic compatibility: does it return or modify the same logical data? Above semantics are metadata and tooling assumptions: do drivers, migrations, ORMs, backup scripts, monitoring queries, and privilege-management scripts see the structures they expect? At the operational top are durability, replication, failover, backup, and performance behavior. A migration is only as safe as the highest layer you actually tested.

Compatibility dimension Question to test Evidence
Protocol/session Can the connector authenticate and execute a round trip? Connection success, server identity query, negotiated TLS/authentication details
SQL grammar Does the statement parse on the exact target? Successful prepare/execute or explicit syntax error
SQL semantics Do values, NULLs, collations and functions behave equivalently? Expected-result assertions and type/metadata checks
Metadata Do catalog/system-table queries and driver introspection still work? INFORMATION_SCHEMA, SHOW, connector metadata APIs
Configuration/tools Do variables, option names and utilities exist with equivalent scope? SHOW VARIABLES, tool --version/--help, option-file tests
Replication/recovery Can events and positions be consumed safely? Version-pair matrix, binlog/replica status, controlled replay
Performance Does the same workload meet latency/throughput/resource goals? Measured workload under disclosed conditions

2. First prove which server answered you

A client binary name is weak evidence. A MySQL-branded client can connect to MariaDB, and a MariaDB client can often connect to MySQL. Always begin a compatibility test by asking the server to identify itself and by capturing session settings that can influence behavior.

sql · server identity and behavior fingerprint
SELECT VERSION() AS server_version,       @@version_comment AS version_comment,       @@hostname AS hostname,       @@port AS port,       @@sql_mode AS sql_mode,       @@character_set_server AS server_charset,       @@collation_server AS server_collation,       @@default_storage_engine AS default_engine;SELECT CONNECTION_ID() AS connection_id,       USER() AS login_identity,       CURRENT_USER() AS privilege_identity,       DATABASE() AS current_database;SHOW ENGINES;SHOW PLUGINS;

On MariaDB, VERSION() and the version comment should identify a MariaDB build. On MySQL Community Server, they should identify MySQL. Package vendors can add build text, so record the whole result rather than parsing only the leading number. The SQL mode, default character set/collation, and engine inventory matter because identical application SQL can diverge when these defaults differ.

What this proves

This fingerprint proves the identity and selected runtime state of the endpoint you reached. It does not prove that a replica, failover target, or another environment has the same values, and it does not prove that a connector feature is supported merely because the session opened.

3. Shared syntax is useful—but syntax is the shallowest SQL test

Both products understand core relational statements such as CREATE TABLE, SELECT, INSERT, joins, transactions, indexes, views, and many functions. That common surface is valuable. But a migration test must move from parser success to behavior assertions. For example, a table definition can parse on both products while its default collation, generated-column rules, JSON representation, optimizer choices, or accepted table options differ.

sql · portable-looking ServiceHub probe
CREATE DATABASE IF NOT EXISTS servicehub_compat;USE servicehub_compat;DROP TABLE IF EXISTS tickets;CREATE TABLE tickets (  ticket_id BIGINT NOT NULL AUTO_INCREMENT,  customer_code VARCHAR(32) NOT NULL,  priority TINYINT NOT NULL DEFAULT 3,  payload JSON NULL,  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,  PRIMARY KEY (ticket_id),  UNIQUE KEY uq_ticket_customer (customer_code)) ENGINE=InnoDB;INSERT INTO tickets(customer_code,priority,payload)VALUES ('ACME-001',2,'{"source":"mobile","region":"west"}');SHOW CREATE TABLE tickets;SHOW FULL COLUMNS FROM tickets;SELECT ticket_id, customer_code, priority,       JSON_EXTRACT(payload,'$.source') AS sourceFROM tickets;

The important artifact is not merely “query succeeded.” Save SHOW CREATE TABLE, column metadata, returned values, warnings, and SQL mode. Later in this chapter you will run deliberately divergent probes. The compatibility notebook should therefore distinguish supported and equivalent, supported but different, unsupported, and not yet tested.

4. Metadata compatibility is where tooling often breaks

Application frameworks and operational tools frequently query metadata rather than business tables. An ORM can issue INFORMATION_SCHEMA queries to detect generated columns. A monitoring script can read mysql.user. A deployment tool can search for variables such as persisted configuration settings. These queries are part of your compatibility surface even when your application SQL is simple.

MariaDB, for example, stores modern global privilege records in mysql.global_priv, while mysql.user is retained as a compatibility view. A script that directly updates system tables is unsafe even if an old query still appears to work. The stable migration pattern is to use supported account-management statements such as CREATE USER, GRANT, and ALTER USER, then use metadata views for observation.

sql · metadata capability probes
SELECT TABLE_NAME, ENGINE, TABLE_COLLATIONFROM information_schema.TABLESWHERE TABLE_SCHEMA='servicehub_compat'ORDER BY TABLE_NAME;SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, IS_NULLABLE,       COLUMN_DEFAULT, EXTRA, COLLATION_NAMEFROM information_schema.COLUMNSWHERE TABLE_SCHEMA='servicehub_compat'  AND TABLE_NAME='tickets'ORDER BY ORDINAL_POSITION;SHOW VARIABLES LIKE 'gtid%';SHOW VARIABLES LIKE 'wsrep%';SHOW VARIABLES LIKE 'persist%';

Do not turn an empty result into a universal statement about the product. It only shows what the exact target exposes under the chosen variable pattern and installed plugins. Record the server version beside every probe.

5. Optimizer and performance compatibility require measurements, not slogans

Two servers can return identical rows and still choose different access paths, join orders, temporary-table strategies, or cost estimates. That is not automatically a bug. Optimizers are implementation-specific and evolve independently. Therefore a compatibility review should compare the outcome first, then collect plans and measured latency under controlled data, cache, concurrency, and hardware conditions.

sql · plan evidence on MariaDB
EXPLAINSELECT ticket_id, created_atFROM servicehub_compat.ticketsWHERE customer_code='ACME-001';ANALYZESELECT ticket_id, created_atFROM servicehub_compat.ticketsWHERE customer_code='ACME-001';

MariaDB has its own ANALYZE statement for execution statistics. MySQL exposes different plan and runtime-reporting syntax, including EXPLAIN ANALYZE in supported releases. Never copy one engine’s explain syntax or output parser into the other without a version check. For this tiny table, the plan is pedagogical only; do not infer production performance from a one-row dataset.

6. Deliberately wrong: “the connector connected, therefore we are compatible”

Suppose the ServiceHub application uses a MySQL-capable driver. You change the host from MySQL to MariaDB, the health check executes SELECT 1, and the deployment is marked green. Later a migration script runs SET PERSIST, a reporting query assumes MySQL JSON metadata, and a replication cutover expects MySQL GTID auto-positioning. The original smoke test was not false; it was simply testing only the protocol/session layer.

The repair is to convert every implicit dependency into an explicit test category. Keep the connection smoke test, but add schema DDL, generated columns, JSON, collations, representative reads/writes, stored programs, authentication, configuration, backup/restore, replication, and performance. An unsupported or different feature is not automatically a migration blocker if you can redesign around it—but it must not remain unknown.

Production judgment

Use “compatible” only with qualifiers: compatible for this connector version, this SQL corpus, this schema, this source/target pair, and these operational requirements. The shorter the claim, the more likely it hides an untested dimension.

7. Hands-on lab: build the first compatibility matrix

Run the following probes against MariaDB Community 12.3.2. If you have MySQL Community 8.4.11 available, run the same read-only probes there and store outputs in separate files. Both are free local products; a second engine is strongly recommended for this chapter because comparative behavior is the subject. Do not point the lab at production.

sql · compatibility probe set
SELECT VERSION(), @@version_comment;SELECT @@sql_mode, @@character_set_server, @@collation_server;SHOW ENGINES;SHOW PLUGINS;SHOW VARIABLES LIKE 'gtid%';SHOW VARIABLES LIKE 'wsrep%';SHOW VARIABLES LIKE 'persist%';USE servicehub_compat;SHOW CREATE TABLE tickets;SHOW FULL COLUMNS FROM tickets;SELECT ticket_id, customer_code,       JSON_VALID(payload) AS valid_json,       JSON_TYPE(payload) AS json_type,       JSON_EXTRACT(payload,'$.region') AS regionFROM tickets;EXPLAIN SELECT * FROM tickets WHERE customer_code='ACME-001';
Probe MariaDB result MySQL result Classification
Connection and identity Record exact output Record exact output Equivalent / different / not tested
DDL round-trip Save SHOW CREATE TABLE Save output Compare stored definition
JSON metadata Save column type/collation Save metadata Semantic/metadata check
GTID variables Inventory only Inventory only Replication model differs
Plan Save plan Save plan Do not require identical text

Cleanup is optional because the servicehub_compat database will be reused by later lessons. If you need a clean reset, confirm you are on a disposable instance and run DROP DATABASE servicehub_compat;.

Check your understanding

  1. Why is protocol compatibility weaker evidence than SQL semantic compatibility?
  2. Why should SHOW CREATE TABLE be saved during a migration test?
  3. What does a successful SELECT 1 prove—and what does it not prove?
  4. Why can two correct optimizers choose different plans?
  5. What four states should a compatibility matrix distinguish?
Review the answers

Protocol compatibility proves that a client and server can communicate, not that higher-level behavior is equivalent. SHOW CREATE TABLE exposes the definition the target actually stored after parsing/default resolution. A health-check query proves only a minimal session and execution path. Different optimizers may choose different valid access paths because costing and transformations differ. Useful matrix states are supported/equivalent, supported/different, unsupported, and not yet tested.

8. Summary and bridge

MariaDB and MySQL have strong shared heritage, but compatibility is layered and directional. Treat connection success as the beginning of evidence collection, not the end. Identity, SQL semantics, metadata, tools, configuration, replication, and performance each need their own tests. The next lesson makes this more concrete by comparing release numbering, renamed utilities, configuration surfaces, defaults, MariaDB-only capabilities, and MySQL-only administrative mechanisms.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.