主從複制運行一段時間後,發現磁碟空間暴增,罪魁禍首往往是未設定過期清理的 Binary Log。本文詳述 Binlog 過期設定、手動清理、以及誤操作(如 DROP TABLE) 後的資料恢復實戰流程。
SHOW VARIABLES LIKE 'expire_logs_days';
預設值為 0(永不過期)。
SET GLOBAL expire_logs_days = 8;
[mysqld]
expire_logs_days = 8
修改後重啟 MySQL。建議配合備份策略設定天數(如全備週期+1天)。
SHOW BINARY LOGS;
輸出範例:
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 150462942 |
| mysql-bin.000002 | 120332942 |
| mysql-bin.000003 | 141462942 |
+------------------+-----------+
PURGE BINARY LOGS TO 'mysql-bin.000003';
保留 mysql-bin.000003 及之後的檔案。
PURGE BINARY LOGS BEFORE '2024-01-15 10:00:00';
-- 或清理 3 天前
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 3 DAY);
SHOW SLAVE STATUS 確認正在讀取的 Master_Log_File。ROW 或 MIXED(STATEMENT 格式恢復較複雜)。PURGE 或過期清理導致相關 Binlog 遺失。# 檢視 Binlog 內容(可導向檔案較易閱讀)
mysqlbinlog /var/lib/mysql/mysql-bin.000001 > /tmp/binlog_000001.sql
# 搜尋 CREATE TABLE 與 DROP TABLE 位置
grep -n "CREATE TABLE.*xxx_db" /tmp/binlog_000001.sql
grep -n "DROP TABLE.*xxx_db" /tmp/binlog_000001.sql
假設找到:CREATE TABLE 後的 position=20,DROP TABLE 前的 position=1000。
# 必須從 position 4 開始(Format_description_event),否則會報 Duplicate entry 錯誤
mysqlbinlog --start-position=4 --stop-position=1000 /var/lib/mysql/mysql-bin.000001 | mysql -u root -p
為何從 4 開始? Binlog 檔案開頭 4 bytes 為 magic number,position 4 為第一個事件(Format_description_event),包含版本資訊,解析器需由此初始化。
mysqlbinlog --start-datetime="2024-01-14 10:20:00" --stop-datetime="2024-01-15 01:25:00" /var/lib/mysql/mysql-bin.000001 | mysql -u root -p
# 合併多個檔案按順序重放
mysqlbinlog mysql-bin.000001 mysql-bin.000002 mysql-bin.000003 | mysql -u root -p
| 錯誤 | 原因 | 解決 |
|---|---|---|
| ERROR 1062 (23000): Duplicate entry | 重放包含已存在資料的 INSERT | 確保 stop-position 在誤操作之前;或使用 --force 忽略繼續 |
| ERROR 1236: Could not open log file | Binlog 已被清理或路徑錯誤 | 從備份還原 Binlog;檢查 log_bin 路徑 |
| 恢復後資料不全 | Binlog 格式為 STATEMENT,非確定性函數導致主從不一致 | 改用 ROW 格式;或配合全備+增量備份策略 |
binlog_format=ROW,確保恢復準確性。mysqldump --master-data=2 或 XtraBackup。FLUSH LOGS 產生新 Binlog 切割點,便於後續精準恢復。Binlog 是 MySQL 時間機器,善用 expire_logs_days 自動清理、PURGE 手動控制、mysqlbinlog 精準恢復,配合完善備份策略,才能在災難發生時從容應對。切記:沒有測試過的備份,不叫備份。