Binlog 記錄了資料庫所有變更,每筆變更對應一種事件類型。理解事件類型對於同步原理、增量恢復、審計分析至關重要。本文基於 MySQL 5.7 源碼(binlog_event.h),挑選核心事件類型詳細解析,並附 mysqlbinlog 與 SHOW BINLOG EVENTS 實際輸出對照。
enum Log_event_type {
UNKNOWN_EVENT = 0,
START_EVENT_V3 = 1,
QUERY_EVENT = 2, -- 文本 SQL(BEGIN、DDL、STATEMENT 格式 DML)
STOP_EVENT = 3,
ROTATE_EVENT = 4, -- binlog 切換
INTVAR_EVENT = 5,
FORMAT_DESCRIPTION_EVENT = 15, -- binlog v4 首個事件,定義版本/建立時間
XID_EVENT = 16, -- 事務提交 (COMMIT)
TABLE_MAP_EVENT = 19, -- ROW 格式:表映射
WRITE_ROWS_EVENT = 30, -- ROW 格式 INSERT
UPDATE_ROWS_EVENT = 31, -- ROW 格式 UPDATE
DELETE_ROWS_EVENT = 32, -- ROW 格式 DELETE
GTID_LOG_EVENT = 33, -- GTID 事務標識
ANONYMOUS_GTID_LOG_EVENT = 34,
PREVIOUS_GTIDS_LOG_EVENT = 35,
TRANSACTION_CONTEXT_EVENT = 36,
XA_PREPARE_LOG_EVENT = 38,
ENUM_END_EVENT
};
每個 binlog 檔案第一個事件,僅出現一次。定義 binlog 版本、Server 版本、建立時間。MySQL 解析後續事件的基準。
# mysqlbinlog 輸出 # at 4 #160817 11:00:10 server id 1 end_log_pos 120 CRC32 0x03010da1 Start: binlog v 4, server v 5.6.31-log created 160817 11:00:10
用於:
BEGIN包含:thread_id、exec_time、error_code、status_vars(SET TIMESTAMP、SQL_MODE 等上下文)、schema、原生 SQL 文本。
# at 195 #160817 4:53:06 server id 1 end_log_pos 298 CRC32 0xf9049380 Query thread_id=3 exec_time=0 error_code=0 SET TIMESTAMP=1471380786/*!*/; insert into test.t1 values(1,'a') /*!*/;
三種類型:WRITE_ROWS_EVENT、UPDATE_ROWS_EVENT、DELETE_ROWS_EVENT。不記錄 SQL 文本,而是記錄行映像:
需搭配 TABLE_MAP_EVENT 解析表結構。查看時需加 -vv --base64-output=decode-rows。
mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000027'; +------------------+-----+-------------+-----------+-------------+---------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+-------------+-----------+-------------+---------------------------------------+ | mysql-bin.000027 | 188 | Table_map | 1 | 236 | table_id: 80 (test.t1) | | mysql-bin.000027 | 236 | Write_rows | 1 | 278 | table_id: 80 flags: STMT_END_F | | mysql-bin.000027 | 425 | Update_rows | 1 | 475 | table_id: 80 flags: STMT_END_F | | mysql-bin.000027 | 622 | Delete_rows | 1 | 664 | table_id: 80 flags: STMT_END_F | +------------------+-----+-------------+-----------+-------------+---------------------------------------+
無論 STATEMENT 或 ROW 格式,事務提交時必寫入 XID_EVENT,記錄事務 ID(xid)。崩潰恢復時,InnoDB 根據 binlog 是否有 XID 決定是否提交 prepared 事務。
# at 298 #160817 4:53:06 server id 1 end_log_pos 329 CRC32 0xdb58b5b4 Xid = 25 COMMIT/*!*/;
檔案達到 max_binlog_size 或執行 FLUSH LOGS 觸發。記錄下一個 binlog 檔名與起始位置(固定為 4)。
# at 120 #160817 12:34:26 server id 1 end_log_pos 167 CRC32 0xd965567c Rotate to mysql-bin.000029 pos: 4
SET @@SESSION.GTID_NEXT= 'uuid:seq'。# mysql-bin.000033 # at 120 Previous_GTIDs: uuid:1 # at 191 GTID: uuid:2 # at 448 GTID: uuid:3 # mysql-bin.000034 # at 120 Previous_GTIDs: uuid:1-3
MySQL 正常關閉時寫入,表示 binlog 完整結束。崩潰時無此事件。
MySQL 使用 binlog_cache_mngr 緩存事務內所有事件,COMMIT 時一次性刷入 binlog;ROLLBACK 時直接丟棄緩存。非事務引擎(MyISAM)操作立即寫入 binlog,即使後續 ROLLBACK,已寫入的 binlog 不會回滾,需注意主從一致性風險。
| 參數 | 說明 |
|---|---|
max_binlog_size | 單檔最大值(預設 1G),達到時 rotate。事務不拆分跨檔,實際檔案可能略大。 |
sql_log_bin | 會話級開關,SET sql_log_bin=0 禁用當前會話 binlog 記錄。 |
sync_binlog | 控制 fsync 頻率。0 交給 OS(效能最好,風險最高);1 每事務提交 fsync(最安全);N 每 N 個事務組 fsync。5.7.7+ 預設 1。 |
總結:Binlog 事件類型是 MySQL 複製、恢復、審計的基石。熟悉 QUERY_EVENT、ROWS_EVENT、XID_EVENT、GTID_LOG_EVENT、ROTATE_EVENT 等核心類型,配合 mysqlbinlog -vv 與 SHOW BINLOG EVENTS,可精準定位資料變更、排查同步延遲、實施時間點恢復。