MySQL 8.x ile MariaDB 10.x Arasındaki Temel Farklar

Yıllardır MySQL kullanıyorsunuz, her şey yolunda gidiyor, sonra bir gün biri geliyor “biz MariaDB’ye geçelim” ya da tam tersi oluyor. İşte o anda gerçekten ne kadar farklı olduklarını anlamaya başlıyorsunuz. Ben de bu soruyu üretim ortamlarında birkaç kez yaşadım ve her seferinde “bunlar aslında ne kadar farklı?” sorusunu kendime sordum. Bu yazıda MySQL 8.x ile MariaDB 12.x arasındaki farkları salt teorik olarak değil, günlük sistem yönetimi perspektifinden ele alacağız.

Tarihsel Arka Plan: Neden İki Ayrı Proje Var?

MySQL, 2010 yılında Oracle tarafından satın alındığında MySQL’in orjinal geliştiricilerinden Michael “Monty” Widenius bu durumu pek de iç açıcı bulmadı ve MariaDB’yi fork ederek bağımsız bir proje olarak geliştirmeye başladı. İlk yıllarda iki proje birbirine oldukça yakındı, hatta çoğu dağıtım MariaDB’yi MySQL’in drop-in replacement’ı olarak sunuyordu. Ancak 2024-2025 itibarıyla bu iki proje gerçek anlamda farklı yönlere evrildi.

MySQL 8.x, Oracle’ın kurumsal vizyonuyla şekilleniyor: JSON desteği, window functions, CTE’ler, güçlü InnoDB geliştirmeleri ve özellikle bulut entegrasyonuna odaklanma. MariaDB ise topluluk odaklı, açık kaynak ruhunu koruma iddiasıyla yoluna devam ediyor ve MySQL’e olmayan bazı özellikleri çok daha erken hayata geçiriyor.

Kurulum Farkları

İlk pratik farklılık kurulum aşamasında başlıyor. Özellikle RHEL/Rocky Linux/AlmaLinux gibi enterprise dağıtımlarda bu fark belirgin.

MySQL 8.x kurulumu (RHEL tabanlı):

# Oracle'ın resmi repo'sunu ekle
rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm

# GPG anahtarını içe aktar
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023

# Kurulum
dnf install mysql-community-server -y

# Servisi başlat ve etkinleştir
systemctl enable --now mysqld

# Geçici şifreyi al
grep 'temporary password' /var/log/mysqld.log

# Güvenli kurulum
mysql_secure_installation

MariaDB 12.x kurulumu (RHEL tabanlı):

# MariaDB resmi repo kurulum scripti
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash -s -- --mariadb-server-version="mariadb-12.0"

# Kurulum
dnf install MariaDB-server MariaDB-client -y

# Servisi başlat
systemctl enable --now mariadb

# Güvenlik kurulumu
mariadb-secure-installation

Dikkat ettiyseniz MariaDB’de komut adları değişti. mysql_secure_installation yerine mariadb-secure-installation, mysql client yerine mariadb client geliyor. Eski komutlar hâlâ symlink olarak mevcut ama yeni kurulumlardan itibaren native komutları kullanmaya alışmak daha sağlıklı.

Kimlik Doğrulama: En Can Sıkıcı Fark

MySQL 8.x’in ilk versiyonlarında hayatımızı cehenneme çeviren bir değişiklik vardı: varsayılan kimlik doğrulama eklentisi caching_sha2_password olarak değiştirildi. Eski mysql_native_password ile çalışan her uygulama bağlantı hatası almaya başladı.

# MySQL 8.x'te mevcut authentication plugin'i kontrol et
mysql -u root -p -e "SELECT user, host, plugin FROM mysql.user;"

# Eski uygulamalar için kullanıcıyı native password'e geçir
ALTER USER 'uygulama_kullanici'@'localhost' 
IDENTIFIED WITH mysql_native_password 
BY 'guclu_sifre_buraya';

# Ya da yeni kullanıcı oluştururken belirt
CREATE USER 'yeni_kullanici'@'%' 
IDENTIFIED WITH caching_sha2_password 
BY 'guclu_sifre_buraya';
FLUSH PRIVILEGES;

MariaDB’de ise durum farklı. MariaDB ed25519 ve unix_socket eklentilerini çok daha önce hayata geçirdi. Root kullanıcısı için varsayılan olarak unix_socket kimlik doğrulaması geliyor, yani root şifresi yerine sistem kullanıcısı doğrulaması yapılıyor.

# MariaDB'de root authentication durumunu kontrol et
mariadb -e "SELECT user, host, plugin FROM mysql.user WHERE user='root';"

# Unix socket ile giriş (şifre gerekmez)
sudo mariadb

# Eğer şifre ile giriş istiyorsanız
sudo mariadb -e "ALTER USER root@localhost IDENTIFIED VIA mysql_native_password USING PASSWORD('sifreniz');"

Bu fark özellikle otomasyon scriptlerinde ve Ansible playbook’larında ciddi sorunlara yol açabiliyor. MariaDB’de sudo ile direkt mariadb çağırabilirsiniz ama MySQL’de her zaman şifre ya da socket belirtmeniz gerekiyor.

SQL Uyumluluğu ve Dialect Farklılıkları

İkisi de SQL standardını implemente ediyor ama bazı noktalarda ciddi farklılıklar var.

Window Functions: Her ikisi de destekliyor ama MariaDB bazı durumlarda farklı davranabiliyor.

-- MySQL 8.x ve MariaDB 12.x'te çalışan örnek
SELECT 
    siparis_id,
    musteri_id,
    tutar,
    SUM(tutar) OVER (PARTITION BY musteri_id ORDER BY siparis_tarih) AS kumulatif_toplam,
    ROW_NUMBER() OVER (PARTITION BY musteri_id ORDER BY tutar DESC) AS sira
FROM siparisler
WHERE siparis_tarih >= '2024-01-01';

Invisible Columns: Bu özellik MariaDB’ye özgü ve oldukça kullanışlı.

-- Sadece MariaDB'de çalışır
CREATE TABLE kullanicilar (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    sifre_hash VARCHAR(255) NOT NULL,
    internal_token VARCHAR(64) INVISIBLE,  -- SELECT * ile görünmez
    olusturma_tarihi TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Normal sorgu internal_token'ı getirmez
SELECT * FROM kullanicilar;

-- Explicit belirtmek gerekir
SELECT id, email, internal_token FROM kullanicilar;

Sistem Versioned Tables: MariaDB’nin çok güçlü bir özelliği, temporal tablolar. MySQL’de bu doğrudan yok.

-- MariaDB'de geçmiş veriye erişim
CREATE TABLE urun_fiyatlari (
    id INT PRIMARY KEY,
    urun_adi VARCHAR(100),
    fiyat DECIMAL(10,2)
) WITH SYSTEM VERSIONING;

-- Geçmişteki veriyi sorgula
SELECT * FROM urun_fiyatlari 
FOR SYSTEM_TIME AS OF '2024-06-01 10:00:00';

-- Tüm versiyonları getir
SELECT *, ROW_START, ROW_END 
FROM urun_fiyatlari 
FOR SYSTEM_TIME ALL
WHERE id = 42;

Bu özellik audit log ihtiyacı olan sistemlerde trigger ve log tablosu karmaşasından sizi kurtarıyor. MySQL’de bunu implemente etmek için ciddi ekstra iş gerekiyor.

Storage Engine Farklılıkları

MySQL ve MariaDB her ikisi de InnoDB kullanıyor ama MariaDB burada da bazı eklemeler yapmış.

MariaDB’nin Aria storage engine’i MyISAM’ın crash-safe versiyonu olarak düşünülebilir. Sistem tablolarında ve geçici tablolarda kullanılıyor.

ColumnStore: MariaDB’de büyük veri analitik sorguları için ColumnStore engine mevcut. MySQL’de bu tür ihtiyaçlar için ya HeatWave (Oracle’ın bulut servisi) ya da harici çözümler gerekiyor.

-- MariaDB'de ColumnStore engine ile analitik tablo
-- (ColumnStore ayrı kurulum gerektirebilir)
CREATE TABLE satis_analitik (
    tarih DATE,
    bolge VARCHAR(50),
    urun_kategori VARCHAR(100),
    toplam_satis DECIMAL(15,2),
    adet INT
) ENGINE=ColumnStore;

-- InnoDB ile karşılaştırmalı sorgu performansı test
EXPLAIN SELECT bolge, SUM(toplam_satis) 
FROM satis_analitik 
GROUP BY bolge;

Replikasyon Mimarisi

Replikasyon kurulumu her iki sistemde de benzer ama MariaDB’nin bazı avantajları var.

MySQL 8.x GTID tabanlı replikasyon:

# MySQL 8.x my.cnf - Master
[mysqld]
server-id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = mysql-bin
binlog_format = ROW
binlog_row_image = MINIMAL

# Replica kullanıcısı oluştur
mysql -u root -p << 'EOF'
CREATE USER 'replica_user'@'%' IDENTIFIED WITH mysql_native_password BY 'replica_sifre';
GRANT REPLICATION SLAVE ON *.* TO 'replica_user'@'%';
FLUSH PRIVILEGES;
EOF
# MySQL 8.x Slave konfigürasyonu
mysql -u root -p << 'EOF'
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='master_ip',
  SOURCE_USER='replica_user',
  SOURCE_PASSWORD='replica_sifre',
  SOURCE_AUTO_POSITION=1;
START REPLICA;
SHOW REPLICA STATUSG
EOF

Dikkat: MySQL 8.x’te eski SLAVE syntax’ı deprecated oldu. REPLICA kullanılması gerekiyor. Bu değişiklik scriptlerinizde sessiz sedasız hata üretebilir.

MariaDB GTID replikasyonu:

# MariaDB /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server_id = 1
log_bin = mariadb-bin
binlog_format = ROW
gtid_strict_mode = ON
log_slave_updates = ON

# Replica konfigürasyonu (MariaDB syntax)
mariadb -u root << 'EOF'
CHANGE MASTER TO
  MASTER_HOST='master_ip',
  MASTER_USER='replica_user',
  MASTER_PASSWORD='replica_sifre',
  MASTER_USE_GTID=slave_pos;
START SLAVE;
SHOW SLAVE STATUSG
EOF

MariaDB hâlâ SLAVE syntax’ını destekliyor ve REPLICA alias’ı da eklediler. Ancak GTID implementasyonları farklı çalışıyor. MySQL’de GTID server_uuid:transaction_id formatında iken MariaDB’de domain_id-server_id-sequence_number formatında. Bu fark, MySQL’den MariaDB’ye ya da tam tersine migration yaparken ciddi headache yaratıyor.

Performans ve Query Optimizer Farklılıkları

Burada net bir “biri diğerinden hızlı” demek çok doğru olmaz. Workload tipine göre değişiyor.

OLTP workload’ları: MySQL 8.x InnoDB’nin buffer pool yönetimi ve özellikle innodb_dedicated_server özelliği dikkat çekiyor.

# MySQL 8.x - sunucu RAM'ini otomatik algılayıp InnoDB'yi ayarla
# my.cnf
[mysqld]
innodb_dedicated_server = ON
# Bu ayar şunları otomatik yapar:
# innodb_buffer_pool_size = RAM'in %70-80'i
# innodb_redo_log_capacity = buffer pool'a göre hesaplanır
# innodb_flush_method = O_DIRECT_NO_FSYNC

MariaDB için eşdeğer manuel ayarlama:

# /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
# 32GB RAM'li sunucu için örnek
innodb_buffer_pool_size = 22G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 2G
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT

# MariaDB'ye özgü optimizer ayarları
optimizer_switch = "index_merge=on,index_merge_union=on,
index_merge_sort_union=on,index_merge_intersection=on,
rowid_filter=on"

# Thread pool - MariaDB community edition'da dahili gelir
# MySQL'de bu Enterprise özelliği
thread_handling = pool-of-threads
thread_pool_size = 32

Thread Pool farkı kritik: MySQL Community Edition’da thread pool yok, bu özellik MySQL Enterprise’a ait. MariaDB’de ise topluluk sürümünde thread pool dahili geliyor. Yüksek concurrent connection senaryolarında MariaDB burada önemli bir avantaj sunuyor.

JSON Desteği

MySQL 8.x JSON konusunda gerçekten güçlü. JSON_TABLE, JSON_SCHEMA_VALID gibi fonksiyonlar var.

-- MySQL 8.x JSON_TABLE kullanımı
SELECT *
FROM JSON_TABLE(
  '[{"id": 1, "ad": "Ali", "puan": 95},
    {"id": 2, "ad": "Veli", "puan": 87}]',
  '$[*]' COLUMNS (
    id INT PATH '$.id',
    ad VARCHAR(50) PATH '$.ad',
    puan INT PATH '$.puan'
  )
) AS t;

-- JSON Schema validation (MySQL 8.0.17+)
SELECT JSON_SCHEMA_VALID(
  '{"type": "object", "properties": {"ad": {"type": "string"}, "yas": {"type": "integer"}}}',
  '{"ad": "Mehmet", "yas": 30}'
) AS gecerli;

MariaDB 12.x de JSON_TABLE’ı destekliyor ama bazı JSON fonksiyonlarının implementasyonu farklı. MariaDB’de JSON aslında LONGTEXT olarak saklanıyor ve constraint ile doğrulanıyor, MySQL’de ise gerçek binary JSON formatı kullanılıyor. Bu fark büyük JSON payload’larında performansa yansıyabiliyor.

-- MariaDB'de JSON kullanımı - benzer ama bazı farklar var
CREATE TABLE olay_loglari (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    olay_tipi VARCHAR(50),
    veri JSON,  -- MariaDB'de LONGTEXT olarak saklanır ama JSON constraint uygulanır
    olusturma_zamani TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6),
    CHECK (JSON_VALID(veri))
);

-- JSON path sorguları MariaDB'de de çalışır
SELECT id, JSON_VALUE(veri, '$.kullanici_id') AS kullanici_id
FROM olay_loglari
WHERE JSON_VALUE(veri, '$.olay_tipi') = 'login'
AND olusturma_zamani > NOW() - INTERVAL 1 HOUR;

Yedekleme ve Recovery Farkları

Her iki sistemde de mysqldump çalışıyor ama bazı flag’ler farklı davranabiliyor.

# MySQL 8.x yedekleme - GTID bilgisiyle
mysqldump 
  --single-transaction 
  --routines 
  --triggers 
  --events 
  --set-gtid-purged=ON 
  --source-data=2 
  -u root -p 
  --all-databases > /backup/mysql_full_$(date +%Y%m%d_%H%M).sql

# Sıkıştırılmış backup
mysqldump --single-transaction --all-databases -u root -p | 
  gzip -9 > /backup/mysql_$(date +%Y%m%d).sql.gz
# MariaDB yedekleme
mariadb-dump 
  --single-transaction 
  --routines 
  --triggers 
  --events 
  --master-data=2 
  -u root 
  --all-databases > /backup/mariadb_full_$(date +%Y%m%d_%H%M).sql

# MariaDB Backup (Percona XtraBackup'ın MariaDB native versiyonu)
# mariadb-backup, mariabackup olarak da bilinir
mariabackup 
  --backup 
  --target-dir=/backup/mariadb_physical_$(date +%Y%m%d) 
  --user=root 
  --socket=/var/lib/mysql/mysql.sock

# Restore için prepare adımı
mariabackup --prepare 
  --target-dir=/backup/mariadb_physical_20250115

MySQL için Percona XtraBackup kullanmak hâlâ yaygın bir pratik. MariaDB için ise mariabackup tercih edilmeli çünkü MariaDB’nin InnoDB varyantı (MariaDB InnoDB) bazı sayfa formatı değişiklikleri içeriyor ve XtraBackup her zaman uyumlu olmayabiliyor.

Migrasyon Senaryoları: MySQL’den MariaDB’ye

Bu gerçek dünyada en sık karşılaşılan senaryo. Birkaç kritik kontrol yapmanız gerekiyor.

# Mevcut MySQL'den schema ve veriyi dump et
mysqldump 
  --single-transaction 
  --set-gtid-purged=OFF 
  --skip-add-locks 
  --routines 
  --triggers 
  -u root -p 
  production_db > /tmp/migration_$(date +%Y%m%d).sql

# MariaDB'ye aktar
mariadb -u root production_db < /tmp/migration_$(date +%Y%m%d).sql

# Uyumluluk kontrolü - bu sorguları çalıştırın
mariadb -u root production_db << 'EOF'
-- MySQL 8.x'e özgü fonksiyon kullanımı var mı?
SELECT routine_name, routine_type 
FROM information_schema.routines 
WHERE routine_schema = 'production_db';

-- Kullanılan storage engine'leri kontrol et
SELECT TABLE_NAME, ENGINE 
FROM information_schema.TABLES 
WHERE TABLE_SCHEMA = 'production_db'
AND ENGINE NOT IN ('InnoDB', 'MyISAM', 'Aria', 'MEMORY');
EOF

Migrasyon sırasında dikkat edilmesi gereken başlıca noktalar:

  • caching_sha2_password: MySQL’de bu plugin ile oluşturulmuş kullanıcılar MariaDB’ye taşımada sorun çıkarır. Dump öncesi mysql_native_password‘e geçirin.
  • ROW_FORMAT=COMPRESSED: MariaDB bu formatı destekliyor ama bazı versiyonlarda farklı davranabiliyor.
  • Check Constraints: MySQL 8.0.16 öncesi check constraint’leri parse ediyordu ama enforce etmiyordu. Eğer eski bir MySQL dump’ından geliyorsanız MariaDB bu constraint’leri enforce edecektir.
  • utf8mb4_0900_ai_ci collation: MySQL 8.x’in varsayılan collation’ı MariaDB’de yok. MariaDB’de utf8mb4_unicode_ci kullanmanız gerekiyor.
-- Collation dönüşümü için sorgu üret
SELECT CONCAT(
  'ALTER TABLE ', TABLE_NAME, 
  ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'
)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'production_db'
AND TABLE_COLLATION = 'utf8mb4_0900_ai_ci';

Monitoring ve Observability

Her iki sistemde de Performance Schema mevcut ama MariaDB bazı ek araçlar sunuyor.

-- MySQL 8.x - sys schema ile yavaş sorgu analizi
SELECT 
  query,
  exec_count,
  avg_latency,
  rows_examined_avg,
  rows_sent_avg
FROM sys.statement_analysis
ORDER BY avg_latency DESC
LIMIT 20;

-- MariaDB - benzer analiz
SELECT 
  DIGEST_TEXT,
  COUNT_STAR,
  ROUND(AVG_TIMER_WAIT/1000000000, 3) AS avg_ms,
  SUM_ROWS_EXAMINED,
  SUM_ROWS_SENT
FROM performance_schema.events_statements_summary_by_digest
ORDER BY AVG_TIMER_WAIT DESC
LIMIT 20;
# MySQL 8.x - slow query log aktif et
mysql -u root -p << 'EOF'
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL log_queries_not_using_indexes = ON;
EOF

# MariaDB - aynı parametreler geçerli
mariadb -u root << 'EOF'
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mariadb/slow.log';
SET GLOBAL log_queries_not_using_indexes = ON;
-- MariaDB'ye özgü ek log seçeneği
SET GLOBAL log_slow_verbosity = 'query_plan,explain';
EOF

log_slow_verbosity özelliği MariaDB’ye özgü ve yavaş sorgular için otomatik EXPLAIN çıktısı üretiyor. MySQL’de bunu pt-query-digest gibi harici araçlarla yapmak gerekiyor.

Hangi Durumda Hangisini Tercih Etmeli?

Pratik karar kriterleri:

MySQL 8.x’i tercih edin eğer:

  • Oracle’ın resmi desteğine ihtiyacınız varsa
  • MySQL Cluster (NDB) kullanıyorsanız
  • AWS RDS, Google Cloud SQL gibi managed servisleri kullanıyorsanız (bunlar genellikle MySQL’e optimize)
  • Mevcut uygulama MySQL 8.x ile test edilmiş ve sertifikalandırılmışsa
  • JSON işlemleri yoğunsa ve binary JSON formatının performans avantajından yararlanmak istiyorsanız

MariaDB 12.x’i tercih edin eğer:

  • Thread pool’a topluluk sürümünde ihtiyacınız varsa
  • System Versioned Tables gibi temporal veri özelliklerine ihtiyacınız varsa
  • Galera Cluster kuracaksanız (MariaDB Galera çok daha olgun)
  • Invisible Columns gibi schema yönetim kolaylıklarına değer veriyorsanız
  • Açık kaynak lisans ve topluluk desteği önceliğinizse
  • ColumnStore ile analitik workload’larını aynı veritabanında çalıştırmak istiyorsanız

Sonuç

MySQL 8.x ve MariaDB 12.x, ortak bir atadan gelseler de artık birbirinden belirgin şekilde ayrışmış iki farklı veritabanı sunucusu. “MariaDB, MySQL’in drop-in replacement’ıdır” cümlesi 2015 yılında doğruydu, 2025’te artık bu kadar basit değil.

Syntax düzeyinde yüzde doksanı uyumlu ama o kalan yüzde onluk fark, özellikle replikasyon kurulumunda, kimlik doğrulamada, collation’larda ve yedekleme süreçlerinde kendini gösteriyor. Bir sistemden diğerine geçiş yapmak imkânsız değil ama “export edin, import edin, bitti” kadar da basit değil. Hem uygulama katmanını hem de tüm operasyonel süreçlerinizi gözden geçirmeniz gerekiyor.

En önemli tavsiyem şu: Hangi sistemi kullanırsanız kullanın, her iki sistemin de tuzaklarını bilmek sizi hem migrasyon anında hem de production sorunlarını debug ederken çok daha hazırlıklı yapacak. Ve evet, mysql_native_password deprecated uyarısını bir gün mutlaka ciddiye alacaksınız, ne kadar ertelerseniz erteyleyin.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir