Binlog (二進制日誌) 是 MySQL 數據變更的完整記錄,核心用途:主從同步、時間點恢復 (PITR)、審計追蹤、異常數據溯源。本文系統整理 Binlog 格式、查看命令、mysqlbinlog 實戰參數、遠程解碼、搜尋腳本化。
| 格式 | 記錄內容 | 優點 | 缺點 | 搜尋難度 |
|---|---|---|---|---|
| STATEMENT | 原始 SQL 語句 | 體積小、可直接讀、易審計 | 非確定性函數 (NOW, UUID, RAND) 導致主從不一致、存儲過程/觸發器複雜場景易出錯 | 低 (grep 即可) |
| ROW | 每行變更的前後值 | **數據完整性最高、主從絕對一致、支援所有場景**、可見真實列值 | 體積大 (大批量 UPDATE/DELETE)、需解碼才可讀 | 高 (需 --base64-output=DECODE-ROWS -v) |
| MIXED | 自動選擇 | 折衷 | 行為不可預測、調試困難 | 中 |
生產強制建議:binlog_format=ROW,binlog_row_image=FULL (記錄全列值,利於解碼搜尋)。
-- 1. 查看第一個 Binlog 文件事件
SHOW BINLOG EVENTS;
-- 2. 查看指定 Binlog 文件
SHOW BINLOG EVENTS IN 'mysql-bin.000002';
-- 3. 查看當前正在寫入的 Binlog 文件及位置
SHOW MASTER STATUS\G
-- 4. 獲取所有 Binlog 文件列表
SHOW BINARY LOGS;
限制:僅適合少量事件快速查看,大文件/歷史文件極慢、佔用主庫資源。
# 基本語法
mysqlbinlog [options] log_file1 log_file2 ...
# 關鍵參數
--base64-output=DECODE-ROWS # ROW 格式解碼為可讀偽 SQL (必加)
-v, --verbose # 詳細模式,配合 DECODE-ROWS 顯示列名、值 (必加)
-vv # 更詳細,顯示列類型、長度等元數據
--start-datetime='YYYY-MM-DD HH:MM:SS' # 起始時間過濾
--stop-datetime='YYYY-MM-DD HH:MM:SS' # 結束時間過濾
--start-position=N # 起始位點
--stop-position=N # 結束位點
-d, --database=db_name # 僅顯示指定庫事件 (配合 ROW 格式需解碼後過濾)
--tables=table1,table2 # 僅顯示指定表 (需解碼)
--rewrite-db='from_db->to_db' # 庫重命名 (恢復到不同庫)
--result-file=output.sql # 輸出到文件
--no-defaults # 忽略配置文件
--force-if-open # 強制讀取正在寫入的 Binlog (極度危險,禁用!)
--read-from-remote-server # 從遠程主庫讀取 (配合 -h -u -p -P)
-R, --raw # 原始二進制輸出 (用於備份/傳輸)
# 1. 時間範圍查看 (最常用)
mysqlbinlog --start-datetime='2024-01-15 10:00:00' --stop-datetime='2024-01-15 11:00:00' \
--base64-output=DECODE-ROWS -v -d mydb mysql-bin.000010 > /tmp/binlog_10_11.sql
# 2. 位點範圍查看 (精確恢復)
mysqlbinlog --start-position=12345 --stop-position=67890 \
--base64-output=DECODE-ROWS -v mysql-bin.000010 > /tmp/binlog_pos.sql
# 3. 搜尋特定表/列/值 (管線過濾)
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000010 | \
grep -A 5 -B 5 'table_name.*users' | \
grep -A 10 -B 2 'email.*admin@test.com'
mysqlbinlog -u repl_user -p'ReplPass' -h db-master.example.com -P 3306 \
--read-from-remote-server \
--start-datetime='2024-01-15 23:00:00' --stop-datetime='2024-01-15 23:30:00' \
mysql-bin.000001 > /tmp/remote_binlog.sql
# 關鍵點:
# 1. 需遠程用戶有 REPLICATION SLAVE 權限
# 2. 不要讀取當前正在寫入的活躍 Binlog (--force-if-open 禁用)
# 3. ROW 格式必加 --base64-output=DECODE-ROWS -v
# 4. 輸出重定向到本地文件分析,避免終端緩衝區溢出
#!/bin/bash
# binlog_grep.sh - 批量解碼搜尋
# 用法: ./binlog_grep.sh "keyword1" "keyword2" ...
BINLOG_DIR="/home/data/mysql/binlog"
WORK_DIR="/tmp/binlog_grep_$$"
MYSQLBINLOG="/usr/local/mysql/bin/mysqlbinlog"
KEYWORDS=("$@")
mkdir -p "$WORK_DIR"
cd "$WORK_DIR"
cp "$BINLOG_DIR"/mysql-bin.* . 2>/dev/null
GREP_CMD="grep ${KEYWORDS[0]}"
for kw in "${KEYWORDS[@]:1}"; do GREP_CMD="$GREP_CMD | grep $kw"; done
for f in mysql-bin.*; do
echo "=== $f ===" >> summary.log
eval "$MYSQLBINLOG --base64-output=DECODE-ROWS -v $f | $GREP_CMD" >> summary.log 2>&1
eval "$MYSQLBINLOG --base64-output=DECODE-ROWS -v $f | $GREP_CMD" >> detail.log 2>&1
done
[ -s detail.log ] && echo "FOUND" || echo "NOT FOUND in retention"
ls -lh summary.log detail.log
-v 可能不顯示列值,-vv 保證完整解碼。mysqlbinlog 版本應 ≥ MySQL Server 版本,舊版工具無法解析新版 Binlog 事件 (如 8.0 的 GTID、部分事件類型)。> file.sql。--skip-gtids 或配合 SET @@SESSION.GTID_NEXT。pt-query-digest --type=binlog 分析 Binlog 慢查詢/頻繁表。Binlog 是 MySQL 的「黑盒記錄儀」。掌握 mysqlbinlog --base64-output=DECODE-ROWS -v 解碼核心參數、**時間/位點範圍過濾**、**遠程讀取**、**管線過濾搜尋**、**腳本化批量掃描**,並建立**增量解碼索引**體系,才能從海量二進制日誌中精準溯源數據變更真相。