首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 存儲程序、函數、觸發器與複寫:相容性、安全限制與最佳實踐

     編輯:MySQL 資料庫相關知識

複寫相容性總覽

項目是否複寫說明
存儲程序/函數 定義 (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 模式執行(錯誤轉警告),或拆分小批次、應用層冪等重試。

最佳實踐清單

  1. 所有存儲程序/函數明確宣告 DETERMINISTIC / NOT DETERMINISTIC / READS SQL DATA / MODIFIES SQL DATA。
  2. 避免在程序中使用 UUID()、RAND()、NOW()、SYSDATE()、FOUND_ROWS() 等非確定性函數。
  3. 複寫環境強制啟用 ROW 格式 binlog (binlog_format=ROW),避免 STATEMENT 格式下的不確定性。
  4. 定期執行 pt-table-checksum 驗證主從資料一致性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved