MariaDB'de binary log (ikili günlük), veritabanındaki veriyi ve yapıyı değiştiren her ifadenin sırayla kaydedildiği dosyalar dizisidir. Seçenek dosyasına log_bin yazıp sunucuyu yeniden başlatarak açarsınız. Zamana göre kurtarma (point-in-time recovery, PITR) da bu günlüğe dayanır: önce son yedeği geri yüklersiniz, sonra mariadb-binlog ile yedekten sonraki olayları istediğiniz saniyeye kadar yeniden çalıştırırsınız. Böylece örneğin saat 14:05'te yanlışlıkla silinen bir tabloyu 14:04'teki hâliyle geri getirebilirsiniz.

Bu yazıda binary log'un nasıl açıldığını, dosyalarının nasıl düzenlendiğini, üç kayıt biçimini, mariadb-binlog aracını, adım adım PITR'yi, eski dosyaların güvenle silinmesini ve MariaDB 12.3 ile gelen InnoDB tabanlı binary log seçeneğini resmî belgelere göre anlatıyoruz. Binary log'un replikasyondaki rolü replikasyon kurulumu yazısında, yedek almanın kendisi mariadb-dump ve mariadb-backup yazılarında. Serinin haritası için MariaDB öğrenme rehberi.

Binary log ne kaydeder?

Binary log ne kaydeder?

Belgelere göre binary log, veritabanlarındaki hem veri hem yapı değişikliklerinin ve her ifadenin ne kadar sürdüğünün kaydıdır; bir dizi binary log dosyası ile bir indeks dosyasından oluşur. CREATE, ALTER, INSERT, UPDATE ve DELETE kaydedilir; veriyi değiştirmeyen SELECT ve SHOW kaydedilmez. Bunları da görmek isterseniz performans bedeliyle birlikte genel sorgu günlüğü gerekir. Etkilemesi mümkün olup hiçbir satırı etkilemeyen bir UPDATE veya DELETE, ifade tabanlı kayıtta yine de günlüğe yazılır.

Günlüğün iki temel amacı vardır: replikasyonu mümkün kılmak ve yedekleme işlemlerine yardımcı olmak. Belgeler, binary log açık bir sunucunun biraz daha yavaş çalıştığını ve günlüğün parolalar dahil hassas bilgi içerebileceği için korunması gerektiğini belirtir. Dosyalar düz metin değildir; okunabilir hâle getirmek için mariadb-binlog aracı kullanılır.

Binary log, InnoDB ile ikili işlem onayı (two-phase commit) için işlem koordinatörü de olur. Sunucu çökerse, kurtarma sırasında hazırlanmış ama onaylanmamış işlemlerin kimliği binary log'da aranır: kimliği günlükte bulunan işlem onaylanır, bulunmayan geri alınır. Bu yüzden kurtarma için hâlâ gerekli olan bir binary log dosyası silinemez; buna aşağıda tekrar değineceğiz.

Binary log'u açmak

Binary log'u açmak için sunucuyu --log-bin seçeneğiyle başlatır ya da seçenek dosyasına log_bin ekleyip sunucuyu yeniden başlatırsınız. İsterseniz bir taban ad (basename) verebilirsiniz; vermezseniz MariaDB, makinenin UUID'sinden veya ana bilgisayar adından türetilen bir ad kullanır. Belgeler taban ad vermediğinizde --log-basename kullanmanızı şiddetle önerir; aksi hâlde makinenin adı değişirse replikasyon sorun çıkarabilir. Replikasyon için her sunucunun benzersiz bir server_id değerine de ihtiyacı vardır.

ini
[mariadb]
log_bin
server_id=1
log-basename=master1

Taban ada bir uzantı eklerseniz (örneğin .log) belgelere göre sessizce yok sayılır. Yol vermezseniz dosyalar veri dizinine (datadir) yazılır. Sunucu yeniden başladıktan sonra günlüğün açık olduğunu şöyle doğrularsınız:

sql
SHOW VARIABLES LIKE 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+

Seçenek dosyalarının hangi gruplarının okunduğunu ve değişikliklerin nereye yazılacağını my.cnf yapılandırma dosyaları yazısında bulabilirsiniz.

Dosyalar ve indeks

Taban adı bildiğinizde dosyaları diskte de görebilirsiniz. Uzantısı .index olan dosya, mevcut binary log dosyalarının sıralı listesini tutan düz metin bir dosyadır. Asıl günlük dosyaları .000001'den başlayan ardışık numaralar alır; numara büyüdükçe dosya yenidir. MariaDB 11.4'ten itibaren GTID indekslemesi için her dosyanın yanında .idx uzantılı bir dosya da bulunur. Yeni bir günlük dosyası üç durumda açılır: sunucu her başladığında, FLUSH LOGS çalıştırıldığında ve dosya max_binlog_size sınırına ulaştığında.

Dosyaları sunucunun içinden listelemek için SHOW BINARY LOGS, o anda yazılan dosyayı ve konumu görmek için SHOW BINLOG STATUS (eski adıyla SHOW MASTER STATUS) kullanılır. MariaDB 12.3'ten itibaren bu çıktı Gtid_Binlog_Pos sütununu da içerir; daha önce GTID konumu için ayrıca SELECT @@global.gtid_binlog_pos çalıştırmak gerekiyordu. Belgelerdeki 12.3 örneği:

sql
SHOW BINLOG STATUS;
+--------------------+----------+--------------+------------------+-----------------+
| File               | Position | Binlog_Do_DB | Binlog_Ignore_DB | Gtid_Binlog_Pos |
+--------------------+----------+--------------+------------------+-----------------+
| mariadb-bin.000016 |      475 |              |                  | 0-1-2           |
+--------------------+----------+--------------+------------------+-----------------+

Dosyaların nerede durduğunu SHOW VARIABLES LIKE 'log_bin_basename' ile öğrenebilirsiniz; değer, dizin ile taban adın birleşimidir.

Üç kayıt biçimi: STATEMENT, ROW, MIXED

Üç kayıt biçimi: STATEMENT, ROW, MIXED: STATEMENT, Her satırın değişimi ayrı ayrı; DDL yine ifade olarak, MIXED (varsayılan)

Biçimi binlog_format değişkeni belirler ve belgelere göre varsayılan MIXED'tir. Hangi biçimi seçerseniz seçin olaylar ikili biçimde saklanır; fark, neyin kaydedildiğindedir.

BiçimNe kaydedilirArtıDikkat
STATEMENTİfade, çalıştırıldığı gibiEn küçük günlükDeterministik olmayan ifadeler güvensiz
ROWHer satırın değişimi ayrı ayrı; DDL yine ifade olarakEn güvenliDaha fazla yer kaplar
MIXED (varsayılan)Mümkünse ifade, güvensizse satırReplikasyon için güvenli, ROW kadar yer kaplamazBir işlem içinde iki biçim karışabilir

İfade tabanlı kayıtta sunucu güvensiz bir ifade gördüğünde uyarı yazar; belgelerdeki örnek, LIMIT içeren bir ifadenin hangi satırları etkileyeceğinin öngörülemeyeceğini söyleyen uyarıdır. Belgeler deterministik olmayan ifadeler çalıştırıyorsanız MIXED veya ROW kullanmayı önerir. ROW biçiminin bir başka faydası, aşağıda anlatılan Flashback özelliğinin buna dayanmasıdır. Biçimi değiştirmek için:

sql
SET GLOBAL binlog_format = 'ROW';
SHOW VARIABLES LIKE 'binlog_format';

Kaydı oturumda veya veritabanı bazında kapatmak

BINLOG ADMIN yetkisine sahip bir kullanıcı, yalnızca kendi oturumu için kaydı sql_log_bin ile kapatıp açabilir. Bir replikada yerel bakım yaparken bu değişikliklerin günlüğe girmesini istemiyorsanız işe yarar.

sql
SET sql_log_bin = 0;
SET sql_log_bin = 1;

Sunucu genelinde --binlog-ignore-db ve --binlog-do-db seçenekleri de vardır, ancak belgelerin ayrıntılı anlattığı bir tuzakları var. Hangi veritabanının kontrol edildiği, değişikliğin kaydedildiği biçime bağlıdır. Satır olaylarında değişen tablonun veritabanı kontrol edilir. İfade olaylarında ise USE ile seçilmiş varsayılan veritabanı kontrol edilir, ifadenin değiştirdiği tablonun veritabanına bakılmaz. DDL her zaman ifade olarak kaydedildiği için ROW biçiminde bile varsayılan veritabanına göre süzülür. Belgelerdeki örnek: sunucu --binlog-ignore-db=employees ile başlatılmışsa aşağıdaki güncelleme ifade tabanlı kayıtta günlüğe girer (varsayılan veritabanı customers), satır tabanlı kayıtta girmez.

sql
USE customers;
UPDATE employees.details SET bonus=bonus*1.2;

Bu seçenekler virgülle ayrılmış liste kabul etmez, çünkü veritabanı adı virgül içerebilir; birden fazla veritabanı için seçeneği tekrar yazarsınız. Bu tür süzme PITR için tehlikelidir: süzülen bir değişiklik günlükte olmadığı için geri de getirilemez.

mariadb-binlog ile günlüğü okumak

mariadb-binlog (eski adı mysqlbinlog) binary log olaylarını düz metne çevirir. Çıktı doğrudan mariadb istemcisine verilip yeniden çalıştırılabilir. En temel kullanım bir ya da birkaç dosya adı vermektir:

bash
mariadb-binlog mariadb-bin.000152
mariadb-binlog -r outputfile mariadb-bin.000152

Satır tabanlı olaylarda çıktıda SQL ifadesi değil, base64 kodlu satır görüntüleri görürsünüz. -v (--verbose) bu satırlardan okunabilir SQL ifadeleri yeniden kurar, -v -v sütun tiplerini de yorum olarak ekler. Sadece incelemek için --base64-output=decode-rows ile --verbose birlikte kullanılabilir. Belgeler, varsayılan auto dışındaki değerlerin yalnızca hata ayıklama ve test amaçlı olduğunu, bütün olayları çalıştırılabilir biçimde içermeyebileceğini belirtir; sunucuya uygulayacağınız çıktıda bunları kullanmayın.

PITR için en önemli seçenekler aralık belirleyenlerdir:

SeçenekAnlamı
--start-datetimeBu zamana eşit veya sonraki ilk olaydan başla (yerel saat dilimi)
--stop-datetimeBu zamana eşit veya sonraki ilk olayda dur
--start-positionBu konumdan başla; tamsayı yalnızca ilk dosyaya uygulanır, 10.8 ile GTID listesi de olabilir
--stop-positionBu konumda dur; tamsayı yalnızca son dosyaya uygulanır, GTID hâli dahildir
-d, --databaseYalnızca bu veritabanının olayları (tek veritabanı)
-R, --read-from-remote-serverGünlüğü uzak sunucudan oku

--database seçeneği de yukarıdaki süzme kuralına uyar: ifade olaylarında (bütün DDL dahil) USE ile seçilmiş veritabanına, satır olaylarında değişen tablonun veritabanına bakılır. Belgeler ayrıca GTID ile verilen başlangıç ve bitiş konumlarının şu an sıra numaralarını yalnızca alan kimliğine (domain ID) göre karşılaştırdığını, bunun replikasyon tasarımından farklı olduğunu ve bilinen bir hata (MDEV-37231) olarak izlendiğini not eder.

Adım adım zamana göre kurtarma

Senaryo şu olsun: gece alınmış bir yedeğiniz var ve gündüz saat 14:05'te biri yanlışlıkla önemli bir tabloyu sildi. Amaç, yedeği yükleyip ardından 14:05'ten hemen önceki ana kadar olan değişiklikleri uygulamaktır.

1. Başlangıç noktasını bulun. Yedeğiniz mariadb-dump ile --master-data=2 verilerek alındıysa dosyanın başındaki yorum satırında CHANGE MASTER TO MASTER_LOG_FILE=..., MASTER_LOG_POS=... koordinatları durur. mariadb-backup ile alındıysa bu bilgi yedek dizinindeki mariadb_backup_binlog_info dosyasındadır.

2. Binary log dosyalarını güvenceye alın. Kurtarmayı yapacağınız sunucuda günlük dosyalarının üzerine yazılmasın; belgelerdeki mariadb-backup PITR örneğinde yedek yeni bir veri dizinine geri yüklenir ve günlükler eski dizinden okunur.

3. Yedeği geri yükleyin ve sunucuyu başlatın.

4. Olayları SQL betiğine dönüştürün. Belgelerdeki örnekten uyarlanan komut, yedeğin konumundan başlar ve belirtilen zamanda durur:

bash
mariadb-binlog --start-position=321 \
      --stop-datetime="2026-11-05 14:04:59" \
      /var/lib/mysql/mariadb-node4.00001 \
      > mariadb-binlog.sql

5. Betiği gözden geçirip çalıştırın. Belgeler, istemediğiniz ifadeleri (örneğin yanlışlıkla çalışan bir DROP DATABASE) dosyadan silip ardından çalıştırmayı önerir. Dosyayı uygularken --binary-mode kullanılır:

bash
mariadb -u root -p --binary-mode < mariadb-binlog.sql

Birden fazla günlük dosyası varsa hepsini tek bir bağlantıda işleyin. Belgelerin açıkladığı neden: geçici tablolar istemci bağlantısı kapanınca silinir; bir dosya geçici tablo oluşturup sonraki dosya onu kullanıyorsa, dosyaları ayrı bağlantılarla uygulamak 'unknown table' hatasına yol açar. Bunun için dosyaları tek komutta sırayla verirsiniz ya da düzenlemeniz gerekiyorsa önce tek bir dosyada birleştirirsiniz:

bash
mariadb-binlog mariadb-bin.000001 mariadb-bin.000002 | mariadb -u root -p --binary-mode

mariadb-binlog mariadb-bin.000001 > /tmp/mariadb-bin.sql
mariadb-binlog mariadb-bin.000002 >> /tmp/mariadb-bin.sql
mariadb -u root -p -e "source /tmp/mariadb-bin.sql"

Flashback: yanlış DML'i geri sarmak

Bazen yedek yükleyip ileri sarmak yerine son birkaç yanlış değişikliği tersine çevirmek yeterlidir. mariadb-binlog --flashback (-B) satır olaylarını tersine çevirir: INSERT yerine DELETE, DELETE yerine INSERT üretir, UPDATE olaylarında önceki ve sonraki görüntüleri yer değiştirir. Belgelere göre bunun için günlüğün ROW biçiminde ve binlog_row_image=FULL ile tutulması gerekir; yalnızca DML desteklenir, DROP, TRUNCATE veya ALTER geri sarılamaz. Flashback olayları bellekte tutulduğu için sunucuda yeterli bellek olmalıdır. İçe aktarılacak çıktıda -v veya -vv kullanmayın; belgeler bunların içe aktarmada sorun çıkarabileceğini belirtir.

bash
mariadb-binlog /var/lib/mysql/mysql-bin.000001 -d test -T mytable \
    --start-datetime="2013-03-27 14:54:00" --flashback > flashback.sql
mariadb < flashback.sql

Eski günlükleri silmek

Binary log kendiliğinden küçülmez. Belgelere göre expire_logs_days varsayılan olarak 0'dır, yani otomatik silme yoktur. MariaDB 10.6'dan itibaren binlog_expire_logs_seconds daha ince ayar sağlar ve ikisi de sıfırdan farklıysa öncelik ondadır. MariaDB 11.4 ile gelen max_binlog_total_size ise toplam boyuta sınır koyar. Süreye bağlı silme yalnızca günlük döndürüldüğünde kontrol edilir; günlük yavaş doluyorsa eski dosyalar beklediğinizden uzun kalabilir. Düzenli FLUSH BINARY LOGS bunu zorlar. Belgeler süreyi her zaman olası replika gecikmesinden uzun tutmanızı söyler.

sql
SET GLOBAL binlog_expire_logs_seconds = 604800;

Elle silmek için PURGE BINARY LOGS kullanılır; BINARY ve MASTER eş anlamlıdır ve BINLOG ADMIN yetkisi gerekir. Belirtilen dosyadan veya tarihten önceki dosyalar silinir ve indeksten çıkarılır. Tarih biçimi YYYY-MM-DD hh:mm:ss'dir. Bütün günlükleri silmek için RESET MASTER vardır, ama replikasyon veya PITR kullanıyorsanız bunu bilerek yapmalısınız.

sql
PURGE BINARY LOGS TO 'mariadb-bin.000063';
PURGE BINARY LOGS BEFORE '2013-04-22 09:55:22';

Bağlı bir replika hâlâ okuyorsa ifade o dosyada durur: daha eski dosyalar silinir, o dosya ve sonrakiler korunur ve ifade hata vermez. Belgelere göre MariaDB 11.4.3'ten itibaren bu durumda korunan ilk dosyayı adlandıran 1375 numaralı not döner. Replika bağlı değilse dosya silinir ama replika yeniden bağlandığında devam edemez. Bu yüzden belgelerin önerdiği sıra şudur: SHOW BINARY LOGS ile listeyi alın, her replikada SHOW REPLICA STATUS ile hangi dosyayı okuduğuna bakın, en eskiyi bulun ve yalnızca ondan öncekileri silin. Çökme kurtarması için gerekli olan dosyalar da silinmez; belgelerdeki not şöyledir: Binary log 'master-bin.000003' is not purged because it may be needed for crash recovery (XID).

Disk dolarsa ne olur? Belgelere göre MariaDB mevcut günlük dosyasına yazarken disk dolduğunda yazmayı her 60 saniyede bir yeniden dener ve hata günlüğüne her 600 saniyede bir mesaj yazar. Ancak yeni bir günlük dosyası açarken disk doluysa binary log'u süreç boyunca tamamen kapatır; tekrar açmak için sorunu giderip sunucuyu yeniden başlatmanız gerekir. Disk alanını izlemek bu yüzden PITR'nin bir parçasıdır.

MariaDB 12.3: InnoDB tabanlı binary log

MariaDB 12.3 ile isteğe bağlı yeni bir binary log uygulaması geldi; belgeler bunun yapılandırılabilir olduğunu ve varsayılan olmadığını belirtir. binlog_storage_engine=innodb ile açıldığında olaylar InnoDB'nin sayfa yapısını kullanan .ibb uzantılı dosyalara yazılır ve InnoDB'nin redo log'u ile çökme kurtarmasına bağlanır. Bunun getirisi, binary log ile InnoDB arasındaki ikili işlem onayının ortadan kalkması ve innodb_flush_log_at_trx_commit=1 ile işlem başına tek bir eşgüdümlü fsync yapılmasıdır. sync_binlog fiilen yok sayılır; dayanıklılığı yalnızca innodb_flush_log_at_trx_commit belirler.

ini
[mariadb]
log_bin
binlog_storage_engine=innodb

Belgelere göre bu kipte log_bin değer verilmeden yazılmalıdır; dosyalar binlog-000000.ibb gibi adlandırılır, max_binlog_size (varsayılan 1GB) boyutunda önceden ayrılır ve .index, .idx ya da .state dosyaları yoktur. Konumlandırma yalnızca GTID ile yapılır; dosya adı ve konum tabanlı replikasyon, MASTER_POS_WAIT(), BINLOG_GTID_POS() ve RESET MASTER TO kullanılamaz. Yarı eşzamanlı replikasyon, Galera Cluster ve --encrypt-binlog ile binary log şifrelemesi desteklenmez. Birden fazla dosyayı mariadb-binlog ile okurken dosya sınırlarını aşan olayların bir kez görünmesi için hepsini doğru sırayla tek komutta vermeniz gerekir; --start-position ve --stop-position için de GTID konumları önerilir. Belgelere göre yeni biçime geçildiğinde eski binary log dosyaları yok sayılır ve replikaların önce en az 12.3'e yükseltilmesi gerekir; bu yüzden geçişi bir bakım planıyla yapın.

Sık yapılan hatalar

Sık yapılan hatalar: Binary log'u yedekten sonra açmak, Hiç replikası olmayan sunucuda otomatik silmeye güvenmek, Dosyaları işletim sisteminden silmek, Birden çok günlük dosyasını...
  • Binary log'u yedekten sonra açmak: Günlük ancak açıldığı andan sonrasını kaydeder. PITR istiyorsanız günlük yedekten önce açık olmalıdır.
  • Hiç replikası olmayan sunucuda otomatik silmeye güvenmek: slave_connections_needed_for_purge varsayılan 1 olduğu için günlükler silinmez ve disk dolar.
  • Dosyaları işletim sisteminden silmek: .index dosyası güncel kalmaz ve belgelere göre bütün silme yolları başarısız olur. Her zaman PURGE BINARY LOGS kullanın.
  • Birden çok günlük dosyasını ayrı bağlantılarla uygulamak: Geçici tablolar kaybolur ve 'unknown table' hatası alırsınız.
  • --binlog-ignore-db'nin tablo veritabanına baktığını sanmak: İfade olaylarında ve bütün DDL'de varsayılan veritabanına bakılır.
  • Flashback'in DDL'i geri aldığını düşünmek: Yalnızca INSERT, UPDATE ve DELETE geri sarılır.

Sık Sorulan Sorular

Binary log açmak performansı düşürür mü?

Belgeler binary log açık bir sunucunun biraz daha yavaş çalıştığını belirtir. Karşılığında replikasyon ve zamana göre kurtarma imkânı kazanırsınız. MariaDB 12.3'teki InnoDB tabanlı binary log, ikili işlem onayını kaldırarak bu maliyeti azaltmayı hedefler.

Hangi biçimi seçmeliyim?

Belgelere göre varsayılan MIXED replikasyon için güvenlidir ve ROW kadar yer kaplamaz. Flashback kullanmak istiyorsanız ROW biçimi ve binlog_row_image=FULL gerekir.

Binary log dosyalarını mariadb-backup yedekler mi?

Geleneksel dosya tabanlı günlükte yedek yalnızca konumu kaydeder; PITR için günlük dosyalarının kendisini ayrıca saklamanız gerekir. MariaDB 12.3'ün InnoDB tabanlı binary log kipinde ise belgelere göre günlük dosyaları varsayılan olarak yedeğe dahil edilir.

Silinen bir tabloyu binary log ile geri getirebilir miyim?

DROP TABLE bir DDL'dir ve Flashback ile tersine çevrilemez. Yapmanız gereken, son yedeği geri yükleyip mariadb-binlog ile silme anından hemen öncesine kadar ileri sarmaktır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: MariaDB öğrenme rehberi · mariadb-dump ile yedekleme · mariadb-backup ile fiziksel yedek · Replikasyon kurulumu · Hata ve yavaş sorgu günlükleri · Yedekleme stratejileri