binlog-do-db 是 MySQL 複製過濾參數,用於控制「只有指定庫的變更才寫入 Binlog」。但其行為與 binlog_format (STATEMENT/ROW/MIXED) 和當前會話 USE database 狀態強耦合,配置不當極易導致主從數據不一致。本文通過三組對照實驗,深度解析不同場景下的 Binlog 寫入行為,揭示生產環境隱患。
binlog-do-db 在 STATEMENT/MIXED 格式下極不安全,ROW 格式下行為相對可預測但仍有陷阱。生產環境強烈建議避免使用,改用從庫端 replicate-do-db 或 GTID 過濾。
binlog-do-db = bosco1bosco1 (目標庫), bosco2 (非目標庫)mysql> USE bosco2;
mysql> SELECT @@binlog_format; -- STATEMENT 或 ROW
mysql> FLUSH LOGS;
mysql> CREATE TABLE bosco1.bosco1_tb01(id INT);
mysql> CREATE TABLE bosco2.bosco2_tb01(id INT);
mysql> INSERT INTO bosco1.bosco1_tb01(id) VALUES(1);
mysql> INSERT INTO bosco2.bosco2_tb01(id) VALUES(1);
mysql> FLUSH LOGS;
# 只有 Rotate 事件,無任何 DDL/DML 記錄!
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
# at 4
#141026 1:41:09 server id 1303308 end_log_pos 107 Start: binlog v 4
# at 107
#141026 1:43:02 server id 1303308 end_log_pos 150 Rotate to mysql-bin.000014 pos: 4
當 USE 非 binlog-do-db 庫 時,所有操作(含跨庫操作目標庫的表)均不記錄 Binlog,無論 STATEMENT 或 ROW 格式。DDL 也不記錄。
mysql> USE bosco1;
mysql> SET @@binlog_format = ROW;
mysql> FLUSH LOGS;
mysql> CREATE TABLE bosco1.bosco1_tb01(id INT);
mysql> CREATE TABLE bosco2.bosco2_tb01(id INT);
mysql> INSERT INTO bosco1.bosco1_tb01(id) VALUES(1);
mysql> INSERT INTO bosco2.bosco2_tb01(id) VALUES(1);
mysql> FLUSH LOGS;
# DDL 均記錄
CREATE TABLE bosco1.bosco1_tb01(id INT)
CREATE TABLE bosco2.bosco2_tb01(id INT)
# DML:僅記錄目標庫表的 INSERT
BEGIN
Table_map: bosco1.bosco1_tb01 mapped to number 49
WRITE_ROWS: INSERT INTO bosco1.bosco1_tb01 SET @1=1
COMMIT
# bosco2.bosco2_tb01 的 INSERT **不記錄**
ROW 格式下,USE 目標庫 時:DDL 全記錄(跨庫也記錄),DML 僅記錄目標庫表,非目標庫表 DML 被過濾。
mysql> USE bosco1;
mysql> SET @@binlog_format = STATEMENT; -- MIXED 同理
mysql> FLUSH LOGS;
mysql> CREATE TABLE bosco1.bosco1_tb01(id INT);
mysql> CREATE TABLE bosco2.bosco2_tb01(id INT);
mysql> INSERT INTO bosco1.bosco1_tb01(id) VALUES(1);
mysql> INSERT INTO bosco2.bosco2_tb01(id) VALUES(1);
mysql> FLUSH LOGS;
# DDL 全記錄
CREATE TABLE bosco1.bosco1_tb01(id INT)
CREATE TABLE bosco2.bosco2_tb01(id INT)
# DML **全部記錄**(含非目標庫表!)
BEGIN
INSERT INTO bosco1.bosco1_tb01(id) VALUES(1)
COMMIT
BEGIN
INSERT INTO bosco2.bosco2_tb01(id) VALUES(1) <-- 非目標庫表也記錄了!
COMMIT
STATEMENT/MIXED 格式下,USE 目標庫時:所有庫的 DML 均記錄,binlog-do-db過濾**完全失效**。DDL 也全記錄。
| 場景 | binlog_format | USE 數據庫 | DDL 記錄 | 目標庫 DML | 非目標庫 DML |
|---|---|---|---|---|---|
| 1 | STATEMENT/ROW | 非目標庫 | 否 | 否 | 否 |
| 2 | ROW | 目標庫 | 是(全庫) | 是 | 否 |
| 3 | STATEMENT/MIXED | 目標庫 | 是(全庫) | 是 | 是(失效!) |
INSERT INTO target_db.t SELECT * FROM other_db.t 在非目標庫會話下不記錄"binlog-do-db 在 STATEMENT 格式下基於『當前默認數據庫』判斷,而非『實際操作的數據庫』。 ROW 格式下基於『實際修改的表所屬數據庫』判斷。"
| 方案 | 層級 | 優點 | 缺點 |
|---|---|---|---|
replicate-do-db | 從庫 | 不影響主庫 Binlog 完整性,靈活可變 | 從庫需重啟生效,Binlog 仍傳輸全量 |
replicate-wild-do-table | 從庫 | 支援通配符,表級精確控制 | 同左 |
GTID + gtid_purged | 雙端 | 事務級精確過濾,故障轉移安全 | 需 5.6+,配置較複雜 |
| 應用層路由 | 應用 | 源頭控制,無資料庫依賴 | 開發成本高 |
binlog-ignore-db 行為與 binlog-do-db 完全對稱,同樣受 binlog_format 和 USE database 影響,同樣不建議在主庫使用。
binlog_format = ROW,行級記錄,語義明確,支援異構複製gtid_mode=ON, enforce_gtid_consistency=ON,簡化故障轉移與過濾pt-table-checksum / mysqlbinlog 對比主從binlog-do-db 是一個「看似簡單、實則暗坑」的參數。其行為強依賴會話上下文與 Binlog 格式,極易在應用升級、連接池變更、格式切換時產生靜默數據丟失。堅持「主庫全量 Binlog,從庫按需過濾」原則,是構建穩健 MySQL 複製架構的基石。