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

MySQL 預存程序、函數、觸發器與複寫交互完整解析:安全限制、確定性要求與錯誤處理

     編輯:MySQL 資料庫相關知識

複寫機制核心原則

  • 陳述式複寫 (SBR):主庫記錄呼叫語句 (CALL proc()),從庫重放。
  • 列基複寫 (RBR):主庫記錄實際資料變更,從庫重放資料變更 (預設 5.1+)。
  • 混合模式:非確定性語句自動切換 RBR。

建立/修改/刪除 DDL 複寫

  • CREATE PROCEDURE/FUNCTION、ALTER/DROP 透過 DDL 複寫至從庫,雙端結構保持一致。
  • 需確保 log_bin_trust_function_creators=1 或建立者具 SUPER 權限。

執行時行為複寫差異

物件SBR 複寫內容RBR 複寫內容注意事項
預存程序CALL 語句內部 DML 逐行記錄RBR 下不重放 CALL,避免雙重執行
函數SELECT func()內部 DML 逐行記錄函數不可含顯式 COMMIT/ROLLBACK
觸發器觸發 DML 陳述式觸發器內 DML 逐行記錄觸發器本身不直接複寫,隨觸發表 DML 複寫

安全限制:SUPER 權限與 log_bin_trust_function_creators

  • 預設要求建立者具 SUPER,防止非特權用戶建立不安全常式汙染二進制日誌。
  • 放寬選項:SET GLOBAL log_bin_trust_function_creators=1; (需重啟持久化)。
  • 生產建議:維持 SUPER 要求,建立常式納入變更管理流程。

確定性與時間依賴限制

  • 非確定性函數:UUID()、RAND()、NOW()、SYSDATE()、FOUND_ROWS() 等。
    → SBR 下主從結果不一致;RBR 下記錄實際值,但從庫無法重現相同隨機序列。
  • 時間依賴:SLEEP()、基於時間的邏輯。
    → 二進制日誌不記錄時間點,從庫重放時時間已漂移。
  • 解決:宣告 DETERMINISTIC、改用應用層產生隨機值/時間戳傳入參數。

大量 DML 錯誤處理差異

  • 預存程序:非事務表 (MyISAM) 部分更新後報錯 → 主庫部分生效,從庫複寫中斷 → 主從資料不一致。
  • 函數:自動以 IGNORE 語意執行,錯誤被吞噬,不中斷複寫,但可能導致靜默資料差異。
  • 最佳實踐:關鍵業務強制使用 InnoDB + 明確事務控制,避免非事務表。

監控與驗證

# 主庫檢查常式定義
SHOW CREATE PROCEDURE proc_name;
SHOW CREATE FUNCTION func_name;

# 從庫驗證
SHOW SLAVE STATUS\G
# Seconds_Behind_Master = 0 且無錯誤

# 二進制日誌檢查
mysqlbinlog --base64-output=DECODE-ROWS -v binlog.000001 | grep -A5 'CALL\|func_name'

結語

常式與複寫交互的核心矛盾在於程式邏輯的可重放性 vs 分散式一致性。現代架構建議:業務邏輯下沉應用層、資料庫層僅存儲確定性輔助函數、複寫採用 RBR、關鍵路徑強制事務,將複雜度留在可測試、可觀測的應用程式碼中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved