複寫相容性總覽
| 項目 | 是否複寫 | 說明 |
| 存儲程序/函數 定義 (CREATE/ALTER/DROP) | ✅ 是 | 透過 DDL 語句複寫,主從雙方皆建立 |
| 存儲程序/函數 執行過程 內的 DML | ✅ 是 | 逐條記錄 DML 事件到 binlog,不記錄 CALL 語句本身 |
| 觸發器內 DML | ✅ 是 | 同理記錄實際資料變更事件 |
安全限制:為什麼需要 SUPER 或 log_bin_trust_routine_creators?
從庫執行來自主庫 binlog 的任意 SQL,若存儲程序包含危險操作(如 OS 命令、檔案讀寫),將導致嚴重安全風險。MySQL 強制兩種模式二選一:
| 模式 | 設定 | 適用場景 |
| 嚴格模式 (預設) | 建立程序需 SUPER 權限 | 高安全要求、DBA 管控嚴格環境 |
| 信任模式 | SET GLOBAL log_bin_trust_routine_creators = 1; | 開發環境、受信任開發團隊、無 SUPER 權限帳號需建立程序 |
複寫失效/不一致的三大陷阱
1. 非確定性函數
UUID(), RAND(), NOW(), SYSDATE() 等每次呼叫結果不同。
- 主庫執行時產生值 A,從庫重放時產生值 B → 資料不一致。
- 對策:宣告
DETERMINISTIC 或改用應用層生成傳入參數。
2. 時間基準操作
- binlog 僅記錄 DML 事件,不記錄執行時間點。
- 程序中使用
SLEEP()、NOW() 計算業務邏輯,從庫重放時時間上下文不同 → 結果偏移。
- 對策:避免在程序中依賴即時時間,改由應用層傳入固定時間參數。
3. 大批次 DML 部分失敗
- 主庫大批次
INSERT 第 5000 行報錯停止,前 4999 行已提交;從庫重放同樣報錯,但主庫已提交部分資料,從庫全量回滾 → 主從不一致。
- 對策:函數內 DML 自動以
IGNORE 模式執行(錯誤轉警告),或拆分小批次、應用層冪等重試。
最佳實踐清單
- 所有存儲程序/函數明確宣告
DETERMINISTIC / NOT DETERMINISTIC / READS SQL DATA / MODIFIES SQL DATA。
- 避免在程序中使用
UUID()、RAND()、NOW()、SYSDATE()、FOUND_ROWS() 等非確定性函數。
- 複寫環境強制啟用 ROW 格式 binlog (
binlog_format=ROW),避免 STATEMENT 格式下的不確定性。
- 定期執行
pt-table-checksum 驗證主從資料一致性。