誤 DELETE/UPDATE/DROP TABLE 後,Binlog 是「後悔藥」。本文詳細講解基於時間點與基於位置點兩種恢復模式,並提供自動化恢復腳本框架。
log-bin、binlog-format=ROW(推薦)expire_logs_days/binlog_expire_logs_seconds 清理)mysqlbinlog# 查看 Binlog 事件(解碼 ROW 格式) mysqlbinlog --base64-output=DECODE-ROWS -v /var/lib/mysql/mysql-bin.000001 | head -50 # 導出指定時間範圍 SQL 到文件審查 mysqlbinlog --start-datetime="2024-01-15 10:00:00" --stop-datetime="2024-01-15 10:05:00" \ /var/lib/mysql/mysql-bin.000001 > /tmp/review.sql
--start-datetime/--stop-datetime)適用:知大致誤操作時間窗口。
# 1. 恢復全量備份(假設備份時間 02:00) mysql -uroot -p < /backup/full_20240115_0200.sql # 2. 重放 Binlog 到誤操作前一秒(假設誤操作 10:03:15) mysqlbinlog --stop-datetime="2024-01-15 10:03:14" \ /var/lib/mysql/mysql-bin.000001 | mysql -uroot -p # 3. (可選)跳過誤操作,繼續重放後續 mysqlbinlog --start-datetime="2024-01-15 10:03:16" \ /var/lib/mysql/mysql-bin.000001 | mysql -uroot -p
--start-position/--stop-position)🏆 推薦Binlog 事件有唯一 position(偏移量),精準到字節級。
/tmp/binlog_review.sql # 用編輯器搜索關鍵字:DROP、DELETE、UPDATE、TRUNCATE # 記錄誤操作事件的 position(如 # at 123456) # 記錄誤操作前一個事件的 position(如 # at 123000)
# 導出單庫 SQL mysqlbinlog --database=target_db --base64-output=DECODE-ROWS -v \ /var/lib/mysql/mysql-bin.000001 > /tmp/target_db.sql # 恢復到臨時庫驗證 mysql -uroot -p -e "CREATE DATABASE tmp_restore;" mysql -uroot -p tmp_restore < /tmp/target_db.sql
#!/bin/bash # binlog_pitr.sh - Point In Time Recovery 自動化 # 用法: ./binlog_pitr.sh[start_position] set -euo pipefail FULL_BACKUP=$1 BINLOG_FILE=$2 STOP_TYPE=$3 # datetime 或 position STOP_VALUE=$4 START_POS=${5:-} # 1. 恢復全量備份 echo "Restoring full backup..." mysql -uroot -p"$MYSQL_ROOT_PASS" < "$FULL_BACKUP" # 2. 重放到停止點 if [ "$STOP_TYPE" = "datetime" ]; then mysqlbinlog --stop-datetime="$STOP_VALUE" "$BINLOG_FILE" | mysql -uroot -p"$MYSQL_ROOT_PASS" elif [ "$STOP_TYPE" = "position" ]; then mysqlbinlog --stop-position="$STOP_VALUE" "$BINLOG_FILE" | mysql -uroot -p"$MYSQL_ROOT_PASS" fi # 3. 可選:從起始點繼續 if [ -n "$START_POS" ]; then echo "Continuing from position $START_POS..." mysqlbinlog --start-position="$START_POS" "$BINLOG_FILE" | mysql -uroot -p"$MYSQL_ROOT_PASS" fi echo "PITR completed at $(date)"
| 錯誤 | 原因 | 解決 |
|---|---|---|
Could not read entry at offset N: Error in log format | position 值錯誤(非事件邊界) | 用 mysqlbinlog -v 確認事件邊界 # at xxx |
Unknown database 'db' | Binlog 含多庫,未指定 --database | 加 --database=target_db 或全量重放 |
| GTID 衝突 | 目標庫已有 GTID | 目標庫先 RESET MASTER 或用 --skip-gtids |
| 字符集亂碼 | 備份/恢復字符集不一致 | 確保 --default-character-set=utf8mb4 一致 |
binlog_expire_logs_seconds = 604800FLUSH TABLES WITH READ LOCK 或應用層熔斷,防止 Binlog 被覆蓋掌握 Binlog 精準恢復,讓誤操作從「災難」變為「可控小插曲」。