MySQL vs MariaDB: The Complete Comparison


Introduction





MySQL and MariaDB share a common origin but have diverged significantly since MariaDB was forked from MySQL in 2009. While both systems remain largely compatible at the SQL level, their storage engines, optimization strategies, and feature sets have evolved in different directions. Understanding these differences is critical for migration decisions and new project planning.





Divergence History






# Timeline of divergence


timeline:


- year: 1995


event: "MySQL 1.0 released by TCX DataKonsult AB"


- year: 2008


event: "Sun Microsystems acquires MySQL AB for $1B"


- year: 2009


event: "Oracle acquires Sun; MariaDB forked by MySQL founder Monty Widenius"


- year: 2013


event: "MySQL 5.6 (Oracle) diverges further from MariaDB 10.0"


- year: 2018


event: "MySQL 8.0 released with data dictionary rewrite, roles, CTE"


- year: 2024


event: "MariaDB 11.x and MySQL 8.4 LTS diverge on optimizer and engine features"







Key fork motivations:


* **License concerns**: MySQL moved toward Oracle-controlled development; MariaDB remains fully GPL with a community-driven governance model

* **Feature inclusion**: Oracle rejected some community patches that MariaDB adopted

* **Storage engine philosophy**: MariaDB encourages engine diversity; MySQL centralizes around InnoDB




Storage Engine Differences





InnoDB (Both) vs Aria (MariaDB)






-- MySQL/MariaDB: InnoDB configuration


-- Both support this, but default settings differ




-- MySQL default:


innodb_buffer_pool_size = 70% of RAM


innodb_log_file_size = 2GB


innodb_flush_log_at_trx_commit = 1 -- ACID compliant


innodb_io_capacity = 2000


innodb_autoinc_lock_mode = 2 -- Interleaved (MySQL 8+)




-- MariaDB default:


innodb_buffer_pool_size = 50% of RAM


innodb_log_file_size = 512MB


innodb_flush_log_at_trx_commit = 1


innodb_io_capacity = 200


-- MariaDB also defaults to InnoDB for transactional tables







MariaDB's Aria engine (fork of MyISAM):






-- Create Aria table (MariaDB only)


CREATE TABLE analytics_events (


event_id BIGINT AUTO_INCREMENT,


user_id INT NOT NULL,


event_type VARCHAR(50),


event_data JSON,


created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,


PRIMARY KEY (event_id),


INDEX idx_user (user_id),


INDEX idx_type (event_type)


) ENGINE=Aria TRANSACTIONAL=1 PAGE_CHECKSUM=1;




-- Aria advantages:


-- 1. Crash-safe (unlike MyISAM) without full InnoDB overhead


-- 2. Better performance for read-heavy analytics workloads


-- 3. Lower memory footprint for large tables


-- 4. Supports FULLTEXT indexes




-- MariaDB: ColumnStore for analytical queries


-- Install ColumnStore for columnar storage


-- CREATE TABLE sales_analytics (...) ENGINE=ColumnStore;


-- Optimized for large-scale aggregations







Feature Comparison





Common Features (Both)






-- Both MySQL 8.x and MariaDB 11.x support:


-- Common Table Expressions (CTE)


WITH RECURSIVE org_tree AS (


SELECT id, name, manager_id, 1 AS level


FROM employees WHERE manager_id IS NULL


UNION ALL


SELECT e.id, e.name, e.manager_id, ot.level + 1


FROM employees e


JOIN org_tree ot ON e.manager_id = ot.id


)


SELECT * FROM org_tree ORDER BY level, name;




-- Window functions


SELECT


department,


employee_name,


salary,


RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank,


AVG(salary) OVER (PARTITION BY department) as dept_avg


FROM employees;




-- JSON functions


SELECT JSON_EXTRACT(data, '$.address.city') as city


FROM users WHERE JSON_CONTAINS(data, '{"active": true}');







MariaDB-Only Features






-- Temporal tables (system-versioned)


CREATE TABLE customer_audit (


id INT PRIMARY KEY,


name VARCHAR(100),


email VARCHAR(200),


credit_limit DECIMAL(10,2),


-- Automatic versioning


ROW_START TIMESTAMP(6) GENERATED ALWAYS AS ROW START,


ROW_END TIMESTAMP(6) GENERATED ALWAYS AS ROW END,


PERIOD FOR SYSTEM_TIME (ROW_START, ROW_END)


) WITH SYSTEM VERSIONING;




-- Query historical state


SELECT * FROM customer_audit


FOR SYSTEM_TIME AS OF '2026-01-15 10:00:00'


WHERE id = 42;




-- Dynamic columns (schema-less within column)


CREATE TABLE product_metadata (


product_id INT PRIMARY KEY,


attributes BLOB -- Dynamic columns


);


INSERT INTO product_metadata VALUES (


1,


COLUMN_CREATE('color', 'red', 'weight', 150, 'material', 'steel')


);


SELECT COLUMN_GET(attributes, 'weight' AS INT) as weight


FROM product_metadata WHERE product_id = 1;







MySQL-Only Features






-- MySQL 8.4: Histogram-based optimizer stats


ANALYZE TABLE orders UPDATE HISTOGRAM ON status, customer_id;




-- MySQL: Invisible indexes


ALTER TABLE orders ALTER INDEX idx_order_date INVISIBLE;


-- Test query performance without removing the index




-- MySQL: VECTOR type (MySQL 9.0+)


CREATE TABLE embeddings (


id INT PRIMARY KEY,


embedding VECTOR(1536)


);


CREATE VECTOR INDEX idx_embed ON embeddings ((VECTOR_DISTANCE(embedding, '[...]')));




-- MySQL: Resource groups


CREATE RESOURCE GROUP reporting_group


TYPE = USER


VCPU = 2-3


THREAD_PRIORITY = 5;


SET RESOURCE GROUP reporting_group;


-- Limit analytics queries to specific CPU cores







Performance and Optimization






-- Benchmark: Concurrent OLTP workload


-- Similar performance for basic queries




-- MariaDB thread pool (default in 11.x)


-- Better scalability for high-connection workloads


thread_pool_size = 16


thread_pool_max_threads = 500


thread_pool_idle_timeout = 60




-- MySQL: Connection handling


-- Dedicated thread per connection (default)


-- Or Thread Pool plugin (Enterprise only)


thread_handling = one-thread-per-connection


-- MariaDB includes thread pool free (MySQL charges for it)




-- Query optimizer differences:


-- MySQL 8.4: Cost-based, uses histograms


-- MariaDB 11.x: Cost-based with table statistics feedback loop




-- EXPLAIN output differences


EXPLAIN FORMAT=JSON SELECT * FROM orders WHERE status = 'pending';


-- MySQL: JSON plan with cost breakdown


-- MariaDB: JSON plan with optimization trace







Compatibility and Migration





Application Compatibility





| Feature | MySQL 8.4 | MariaDB 11.x |


|---|---|---|


| SQL syntax | 99% compatible | 99% compatible |


| Data types | 100% compatible (basic) | +Dynamic columns, +INET6 |


| Stored procedures | Compatible | Compatible |


| Triggers | Compatible | Compatible |


| Sequences | Yes (auto_increment) | Yes (SEQUENCE engine) |


| JSON | Native type | LONGTEXT + JSON functions |





Data Replication Between MySQL and MariaDB






# MariaDB as replica of MySQL


[mysqld]


server-id = 2


replicate-do-db = production


binlog_format = ROW


slave_parallel_threads = 4




# Known limitations:


# - GTID formats differ (MariaDB uses own format)


# - Use binlog_checksum = NONE for cross-compatibility


# - Some DDL may not replicate correctly







Migration Steps






# Option 1: Logical dump (most compatible)


mysqldump --compatible=ansi --skip-definer \


--routines --triggers --events \


production_db > backup.sql




# Option 2: Percona XtraBackup (physical)


xtrabackup --backup --target-dir=/backup/mysql




# Option 3: Replication-based (zero-downtime)


# 1. Set up MySQL as master


# 2. Configure MariaDB as replica


# 3. Verify data consistency


# 4. Promote MariaDB to master







Decision Guide




* **Choose MySQL** if you rely on Oracle ecosystem compatibility, need MySQL HeatWave for analytics, require MySQL Enterprise support, or need the VECTOR data type for AI/ML embeddings.

* **Choose MariaDB** if you want fully open-source (no Oracle licensing), need thread pool performance (free), require temporal tables or dynamic columns, prefer a community-governed project, or want storage engine diversity (Aria, ColumnStore, Spider).

* **Stay on current** if you already run either in production without migration pain; the differences are rarely worth a migration for existing deployments.




For new projects starting in 2026, MariaDB offers the better value proposition for most use cases due to its open governance and free enterprise features, while MySQL remains the safer choice for organizations that already have Oracle relationships or need its specific enterprise integrations.