本文基於 MySQL 5.6 官方 PDF 文檔截圖與社區典型博客內容,深度對比 SBR (Statement-Based) 與 RBR (Row-Based) 復制模式下,觸發器、存儲過程、用戶定義函數、調度事件的執行邏輯差異,糾正網上流傳的錯誤認知,給出生產決策依據。
CALL proc(),從庫重放,**從庫必須有定義**,且過程必須 DETERMINISTIC 或不修改數據,否則主從不一致。DISABLED),從庫若啟用會導致雙重執行。Syntax: CREATE [DEFINER = { user | CURRENT_USER }] TRIGGER trigger_name
trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_body
trigger_time: { BEFORE | AFTER }
trigger_event: { INSERT | UPDATE | DELETE }
INSERT/UPDATE/DELETE 生效,**不支持 DDL** (如 ALTER TABLE)。該文聲稱 SBR 下存儲過程「通過系統函數轉換後的值復制,從庫無需建立」,**與 5.6 官方文檔明顯矛盾**。官方明確:SBR 記錄 CALL 語句,從庫重放調用,**必須有定義**。請以官方文檔為準,實測驗證為先。
| 對象 | SBR 行為 | RBR 行為 | 從庫需定義? | 確定性要求 |
|---|---|---|---|---|
| Trigger | 主從雙執行 | 僅主庫執行,行變更入 Binlog | SBR: 是 / RBR: 否 | 無 |
| Stored Procedure | 記錄 CALL,從庫重放 | 行變更入 Binlog,不傳 CALL | SBR: 是 / RBR: 否 | SBR: 必須 DETERMINISTIC |
| Function (UDF) | 記錄調用,從庫重新計算 | 計算結果入行變更,不傳調用 | SBR: 是 / RBR: 否 | SBR: 必須 DETERMINISTIC |
| Event | 定義同步,默認 DISABLED | 同 SBR | 是 (定義同步) | SBR: 函數需確定性 |
UUID()、RAND()、NOW() (在觸發器/函數中) 每次執行結果不同,主從分歧。**強制聲明 DETERMINISTIC 或改用 RBR**。CALL,不記錄觸發器體內的 SQL,故不會「執行兩次」。但從庫仍會執行觸發器體,邏輯重複一次。新架構選型 → 首選 RBR (binlog_format=ROW)
│
├─ 能否接受「從庫不執行觸發器/過程/函數」?
│ ├─ 能 → 徹底清理 DB 端邏輯,遷移到應用層,RBR 無憂
│ └─ 不能 (強依賴 DB 端邏輯)
│ ├─ 評估風險:是否可改造為應用層實現?
│ └─ 必須保留 → 僅相關表/庫強制 SBR (SET SESSION binlog_format=STATEMENT)
│ └─ 嚴格審計:所有函數/過程 DETERMINISTIC,DEFINER 一致,禁用非確定性函數
│
既有 SBR 環境遷移 RBR → 分階段驗證:備庫先改 RBR 跑流量影子表 → 全量驗證無異常 → 主庫切換
MySQL 5.6 官方文檔確立了 RBR 作為復制健壯性的最佳選擇:屏蔽 DB 端程式化對象的復制差異,將複雜度收斂到主庫。生產環境應以 RBR 為默認,SBR 僅作兼容性過渡。觸發器、存儲過程、非確定性函數是復制一致性的三大殺手,**能不用就不用,必用則隔離、審計、實測**。