Yıllarca MySQL ile çalışıp sonra bir gün “MariaDB’ye geçsek mi?” sorusuyla karşılaşmayan sysadmin pek azdır. Oracle’ın MySQL’i satın almasının ardından lisanslama endişeleri, geliştirme hızındaki değişimler ve topluluk desteğinin azalması bu soruyu kaçınılmaz hale getirdi. Ben de bu geçişi hem küçük startup ortamlarında hem de yüzlerce veritabanı sunucusu olan kurumsal yapılarda bizzat yönetttim. Bu yazıda size teknik farkları, geçiş sürecini ve dikkat etmeniz gereken kritik noktaları anlatacağım.
Tarihsel Arka Plan
MariaDB, MySQL’in yaratıcısı Michael “Monty” Widenius tarafından 2009 yılında başlatılan bir fork projesidir. Oracle’ın Sun Microsystems’i (ve dolayısıyla MySQL’i) satın almasından sonra Monty, topluluk odaklı bir alternatif oluşturmak istedi. MariaDB adı, Monty’nin kızının adından geliyor (MySQL de büyük kızı My’dan).
Bugün geldiğimiz noktada MariaDB, artık sadece bir MySQL kopyası değil. Kendi storage engine’leri, kendi optimizer’ı, kendi replication protokolü ve MySQL’de bulunmayan onlarca özelliğiyle tamamen bağımsız bir veritabanı sistemine dönüştü.
Temel Teknik Farklar
Storage Engine Farklılıkları
MySQL ve MariaDB her ikisi de InnoDB kullanıyor, ancak MariaDB’nin kendi geliştirdiği alternatifler mevcut.
Aria Storage Engine: MyISAM’ın crash-safe versiyonu olan Aria, MariaDB’nin varsayılan geçici tablo motorudur. MySQL’de bu iş hala MyISAM ile yapılır.
ColumnStore: Analitik sorgular için sütun tabanlı storage engine. MySQL’de yerleşik olarak bulunmuyor.
MyRocks: Facebook’un geliştirdiği RocksDB tabanlı engine, MariaDB 10.2+ ile birlikte kullanılabilir. Yüksek yazma trafiği olan senaryolarda InnoDB’ye göre çok daha iyi performans sunar.
Spider Engine: Sharding için kullanılan bu engine ile verilerinizi birden fazla sunucuya dağıtabilirsiniz.
JSON Desteği
Bu konuda iki sistem arasında ciddi bir yaklaşım farkı var:
MySQL 5.7+ native JSON data type kullanır ve JSON’ı binary formatta saklar. Bu, okuma performansını artırır ancak bazı kısıtlamalar getirir.
MariaDB ise JSON’ı LONGTEXT olarak saklar ve JSON fonksiyonlarını text üzerinde çalıştırır. MariaDB 10.2 ile birlikte JSON fonksiyonları eklendi ama performans karakteristikleri farklı. MariaDB 10.4’ten itibaren ise bu fark önemli ölçüde kapandı.
-- MySQL'de JSON column
CREATE TABLE kullanici_ayarlari (
id INT PRIMARY KEY,
ayarlar JSON NOT NULL,
olusturma_tarihi DATETIME DEFAULT NOW()
);
-- JSON path query - her iki sistemde de calisiyor
SELECT id, JSON_EXTRACT(ayarlar, '$.tema') AS tema
FROM kullanici_ayarlari
WHERE JSON_EXTRACT(ayarlar, '$.bildirim') = true;
-- MariaDB'de ek olarak JSON_COMPACT ve JSON_DETAILED fonksiyonlari var
SELECT JSON_DETAILED(ayarlar) FROM kullanici_ayarlari LIMIT 1;
Window Functions ve Analitik Sorgular
MariaDB 10.2’den itibaren window function desteği geldi, MySQL ise 8.0 ile bu özelliği kazandı. Eğer hala MySQL 5.7 kullanıyorsanız ve window function ihtiyacınız varsa, MariaDB 10.2+ size bu kapıyı açıyor.
-- Departman icindeki maas siralamasini bul
SELECT
calisan_adi,
departman,
maas,
RANK() OVER (PARTITION BY departman ORDER BY maas DESC) AS maas_sirasi,
SUM(maas) OVER (PARTITION BY departman) AS departman_toplam
FROM calisanlar
ORDER BY departman, maas_sirasi;
Invisible Columns
MariaDB 10.3’te gelen bu özellik MySQL’de yok. Invisible column’lar SELECT * sorgularında görünmez ama direkt referans verildiğinde erişilebilir.
-- MariaDB'ye ozgu: Invisible column
CREATE TABLE audit_log (
id INT PRIMARY KEY AUTO_INCREMENT,
islem VARCHAR(255),
tarih DATETIME DEFAULT NOW() INVISIBLE,
sunucu_ip VARCHAR(45) INVISIBLE
);
-- SELECT * bu kolonlari getirmez
SELECT * FROM audit_log; -- sadece id ve islem gelir
-- Direkt sorguyla erisebilirsiniz
SELECT id, islem, tarih, sunucu_ip FROM audit_log;
Sequence Objects
Oracle ve PostgreSQL kullanıcılarının aşina olduğu sequence objesi MySQL’de yoktur. MariaDB 10.3+ ile birlikte bu özellik geldi.
-- MariaDB'de sequence olusturma
CREATE SEQUENCE siparis_no
START WITH 1000
INCREMENT BY 1
MINVALUE 1000
MAXVALUE 9999999
NOCYCLE;
-- Kullanim
INSERT INTO siparisler (siparis_no, musteri_id)
VALUES (NEXT VALUE FOR siparis_no, 42);
SELECT LASTVAL(siparis_no);
Temporal Tables (System-Versioned Tables)
MariaDB 10.3’te gelen bu özellik, bir tablonun tüm tarihsel değişikliklerini otomatik olarak takip eder. MySQL 8.0’da hala yok.
-- System-versioned table olustur
CREATE TABLE urun_fiyatlari (
urun_id INT,
urun_adi VARCHAR(100),
fiyat DECIMAL(10,2)
) WITH SYSTEM VERSIONING;
-- Guncelleme yap
UPDATE urun_fiyatlari SET fiyat = 150.00 WHERE urun_id = 1;
-- Eski fiyati sorgula
SELECT * FROM urun_fiyatlari
FOR SYSTEM_TIME AS OF '2024-01-15 10:00:00'
WHERE urun_id = 1;
Bu özellik audit trailing, compliance gereksinimleri ve “dün ne vardı?” sorularına cevap vermek için inanılmaz kullanışlı.
Replication Farklılıkları
MariaDB 10.0’dan itibaren GTID (Global Transaction ID) implementasyonu MySQL’den farklı. Bu, migration sırasında en büyük tuzaklardan biri.
MySQL GTID formatı: 3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
MariaDB GTID formatı: 0-1-100 (domain_id-server_id-sequence_no)
Bu fark, MySQL’den MariaDB’ye geçerken replication konfigürasyonunuzu komple yeniden yapmanız gerektiği anlamına gelir.
# MariaDB'de GTID pozisyonunu kontrol et
mysql -u root -p -e "SHOW VARIABLES LIKE 'gtid_current_pos';"
mysql -u root -p -e "SHOW MASTER STATUSG"
# Slave durumunu kontrol et
mysql -u root -p -e "SHOW SLAVE STATUSG"
# MariaDB'de GTID tabanlı replication baslatma
mysql -u root -p -e "
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl_user',
MASTER_PASSWORD='guclu_parola',
MASTER_USE_GTID=slave_pos;
"
Geçiş Süreci: Adım Adım
1. Hazırlık ve Analiz
Geçişe başlamadan önce mevcut ortamınızı iyice analiz edin. Hangi MySQL versiyonundan geçiyorsunuz, uygulama tarafında MySQL’e özel ne kullanıyorsunuz bunları tespit edin.
# Mevcut MySQL versiyonunu ve kullanilan storage engine'leri kontrol et
mysql -u root -p -e "
SELECT
TABLE_SCHEMA,
TABLE_NAME,
ENGINE,
TABLE_ROWS,
ROUND(DATA_LENGTH/1024/1024, 2) AS data_mb
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema')
ORDER BY DATA_LENGTH DESC;
"
# MySQL'e ozgu fonksiyon kullanimi var mi kontrol et
mysql -u root -p -e "
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
FROM information_schema.ROUTINES
WHERE ROUTINE_BODY LIKE '%JSON_TABLE%'
OR ROUTINE_BODY LIKE '%ST_DISTANCE_SPHERE%';
"
JSON_TABLE() MySQL 8.0’a özel bir fonksiyon ve MariaDB’de bulunmuyor. Buna benzer uyumsuzlukları önceden tespit etmek kritik.
2. Yedekleme
Geçiş öncesi kapsamlı yedek almak şart. mysqldump hem MySQL hem MariaDB ile uyumlu çalışır.
# Tum veritabanlarini yedekle
mysqldump
--single-transaction
--routines
--triggers
--events
--all-databases
--master-data=2
-u root -p > /backup/mysql_full_$(date +%Y%m%d_%H%M%S).sql
# Yedek boyutunu kontrol et
ls -lh /backup/mysql_full_*.sql
# Kritik veritabanlari ayri ayri yedekle
for db in $(mysql -u root -p -e "SHOW DATABASES;" | grep -v -E "Database|information_schema|performance_schema|mysql|sys"); do
echo "Yedekleniyor: $db"
mysqldump --single-transaction -u root -p "$db" > /backup/${db}_$(date +%Y%m%d).sql
done
3. MariaDB Kurulumu
# Ubuntu/Debian icin MariaDB repository ekle
curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup |
sudo bash -s -- --mariadb-server-version="mariadb-10.11"
# Paketi kur
sudo apt-get update
sudo apt-get install mariadb-server mariadb-client
# RHEL/CentOS icin
sudo yum install MariaDB-server MariaDB-client
# Servisi baslat
sudo systemctl start mariadb
sudo systemctl enable mariadb
# Temel guvenlik ayarlari
sudo mariadb-secure-installation
4. Konfigürasyon Migrasyonu
MySQL my.cnf dosyanız genellikle MariaDB ile uyumludur ancak bazı parametreler değişmiş ya da kaldırılmıştır.
# MySQL'de kullanilan ama MariaDB'de olmayan parametreleri kontrol et
# query_cache MySQL 8.0'da kaldirildi, MariaDB'de hala var
# innodb_file_format (Barracuda/Antelope) MariaDB'de kaldirildi
# MariaDB icin ornek my.cnf
cat > /etc/mysql/mariadb.conf.d/99-custom.cnf << 'EOF'
[mysqld]
# Temel ayarlar
innodb_buffer_pool_size = 4G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
# MariaDB Query Cache (MySQL 8.0'da yok)
query_cache_type = 1
query_cache_size = 256M
query_cache_limit = 8M
# Karakter seti
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
# Binary log
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
expire_logs_days = 7
# MariaDB GTID
gtid_strict_mode = ON
EOF
5. Veri Aktarımı ve Doğrulama
# MariaDB'ye import et
mysql -u root -p < /backup/mysql_full_20240115_120000.sql
# Import sonrasi tablo sayilarini karsilastir
# MySQL tarafinda
mysql -h mysql_server -u root -p -e "
SELECT TABLE_SCHEMA, COUNT(*) as tablo_sayisi
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY TABLE_SCHEMA;
"
# MariaDB tarafinda ayni sorguyu calistir ve sonuclari karsilastir
mysql -h mariadb_server -u root -p -e "
SELECT TABLE_SCHEMA, COUNT(*) as tablo_sayisi
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY TABLE_SCHEMA;
"
# Satir sayisi kontrolu - kritik tablolar icin
mysql -u root -p -e "
SELECT
CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) AS tablo,
TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'uretim_db'
ORDER BY TABLE_ROWS DESC
LIMIT 20;
"
Performans Farkları: Gerçek Dünya Deneyimleri
Bir e-ticaret projemizde MySQL 5.7’den MariaDB 10.6’ya geçtiğimizde şunları gözlemledik:
Query Cache: MariaDB’de hala aktif olan query cache, bazı okuma ağırlıklı sorgularda %30-40 performans artışı sağladı. MySQL 8.0 bu özelliği kaldırmıştı.
Thread Pool: MariaDB Enterprise ve bazı distro paketlerinde gelen thread pool özelliği, yüksek concurrency durumlarında bağlantı yönetimini dramatik biçimde iyileştiriyor.
# Thread pool aktif etme (MariaDB)
cat >> /etc/mysql/mariadb.conf.d/99-custom.cnf << 'EOF'
[mysqld]
thread_handling = pool-of-threads
thread_pool_size = 16
thread_pool_max_threads = 500
thread_pool_idle_timeout = 60
EOF
# Mevcut thread durumunu izle
mysql -u root -p -e "SHOW STATUS LIKE 'Threadpool%';"
mysql -u root -p -e "SHOW STATUS LIKE 'Threads%';"
Optimizer Farkları: MariaDB’nin query optimizer’ı bazı durumlarda farklı execution plan seçiyor. Bu genellikle iyidir ama bazen de alışılmış sorgularınızın yavaşlamasına yol açabilir.
-- Execution plan karsilastirmasi icin
EXPLAIN FORMAT=JSON
SELECT o.siparis_id, m.musteri_adi, SUM(od.miktar * od.birim_fiyat) AS toplam
FROM siparisler o
JOIN musteriler m ON o.musteri_id = m.musteri_id
JOIN siparis_detay od ON o.siparis_id = od.siparis_id
WHERE o.tarih >= '2024-01-01'
GROUP BY o.siparis_id, m.musteri_adi
ORDER BY toplam DESC
LIMIT 100;
-- Optimizer hint kullanimi (iki sistemde de calisiyor)
SELECT /*+ NO_MERGE(subq) */ *
FROM (SELECT * FROM buyuk_tablo WHERE durum = 'aktif') subq
WHERE subq.toplam > 1000;
Bilinen Uyumsuzluklar ve Tuzaklar
Bu konuda acı çekilmiş bazı gerçek örnekler paylaşayım:
1. Authentication Plugin Farkı: MySQL 8.0 varsayılan olarak caching_sha2_password kullanır. MariaDB ise mysql_native_password kullanmaya devam eder. Özellikle eski PHP uygulamaları bağlantı sorunuyla karşılaşabilir.
# MariaDB'de kullanici olusturma
mysql -u root -p -e "
CREATE USER 'uygulama_user'@'%'
IDENTIFIED BY 'guclu_parola_123!';
GRANT SELECT, INSERT, UPDATE, DELETE
ON uretim_db.*
TO 'uygulama_user'@'%';
FLUSH PRIVILEGES;
"
# Authentication plugin kontrol
mysql -u root -p -e "
SELECT user, host, plugin
FROM mysql.user
WHERE user NOT IN ('root', 'mysql.sys', 'mariadb.sys');
"
2. sql_mode Farkları: MySQL 8.0 çok daha strict bir sql_mode kullanır. MariaDB geçişinde bazı sorgularınız bu yüzden farklı davranabilir.
# Her iki sistemde sql_mode kontrol et
mysql -u root -p -e "SELECT @@sql_modeG"
# Uyumluluk icin sql_mode ayarla
cat >> /etc/mysql/mariadb.conf.d/99-custom.cnf << 'EOF'
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
EOF
3. Decimal Tip Farkı: MariaDB bazı aritmetik işlemlerde farklı hassasiyet davranışı gösterebilir. Finansal uygulamalarda bunu test etmeyi unutmayın.
Hangi Durumda MySQL, Hangi Durumda MariaDB?
MariaDB’yi tercih edin:
- Açık kaynak lisanslama zorunluluğunuz varsa
- MySQL 5.7 kullanıyorsanız ve yükseltme planlıyorsanız
- Temporal tables veya sequence gibi gelişmiş özelliklere ihtiyacınız varsa
- Community desteği ve hızlı güvenlik yamaları önemliyse
- ColumnStore ile analitik sorgular çalıştırmak istiyorsanız
MySQL’de kalın:
- Oracle’ın kurumsal desteğine ihtiyacınız varsa
- MySQL 8.0’a özel özellikleri (JSON_TABLE, CTE improvements) yoğun kullanıyorsanız
- AWS RDS MySQL veya Azure Database for MySQL kullanıyorsanız
- Uygulamanız MySQL Connector’larına sıkı sıkıya bağlıysa
Geri Dönüş Planı
Her geçiş planında mutlaka rollback senaryosu olmalı. MariaDB’den MySQL’e geri dönmek için:
# MariaDB'den dump al
mysqldump
--single-transaction
--routines
--triggers
--all-databases
-u root -p > /backup/mariadb_rollback_$(date +%Y%m%d).sql
# MariaDB'ye ozgu syntax'i MySQL uyumlu hale getir
# Eger temporal table kullandiyseniz bu syntax'i kaldirmak gerekir
sed -i 's/ WITH SYSTEM VERSIONING//g' /backup/mariadb_rollback_*.sql
# MySQL'e geri yukle
mysql -h mysql_original -u root -p < /backup/mariadb_rollback_*.sql
İzleme ve Bakım
Geçiş sonrası ilk hafta yoğun izleme şart. Hem performans hem de hata loglarını takip edin.
# Yavaş sorgu logunu aktif et ve izle
mysql -u root -p -e "
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
"
# Yavaş sorgu logunu analiz et
mysqldumpslow -s t -t 20 /var/log/mysql/mysql-slow.log
# Performans schema ile aktif sorgu izleme
mysql -u root -p -e "
SELECT
DIGEST_TEXT,
COUNT_STAR as calisma_sayisi,
ROUND(AVG_TIMER_WAIT/1000000000, 3) AS ort_sure_sn,
ROUND(SUM_TIMER_WAIT/1000000000, 3) AS toplam_sure_sn
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
"
Sonuç
MariaDB ve MySQL arasındaki geçiş, doğru yapıldığında genellikle sorunsuz bir deneyimdir. Özellikle MySQL 5.7 kullanıyorsanız ve destek süresinin dolmasından sonra ne yapacağınızı düşünüyorsanız, MariaDB 10.6 veya 10.11 LTS sürümleri güçlü birer alternatif.
Benim pratiğimde geçişlerin en büyük riski teknik değil, planlama eksikliğidir. Geçiş öncesi uygulama kodunda MySQL’e özel ne kullandığınızı tespit edin, staging ortamında en az iki hafta test edin, replication GTID farkına dikkat edin ve mutlaka rollback planınız olsun.
MariaDB’nin temporal tables, sequence objects ve gelişmiş analitik özellikleri bir kez kullanmaya başlayınca “bunlar neden MySQL’de yok?” diye sorduğunuzu fark edeceksiniz. Özellikle temporal tables ile audit loglamasını veritabanı seviyesinde çözmek, uygulama geliştiricilerinizi çok mutlu edecek.
Son olarak: hangi sistemi seçerseniz seçin, düzenli yedek alın, monitoring kurun ve güvenlik yamalarını geciktirmeyin. İkisi de production’da güvenle kullanılabilecek olgun sistemler.