錯誤訊息:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
啟用了 Binary Log (log_bin=ON) 時,MySQL 為了確保主從複制安全,要求建立函數/觸發器/事件必須明確宣告其確定性特徵:
DETERMINISTIC:相同輸入必定產生相同輸出 (推薦)NO SQL:不包含 SQL 陳述式READS SQL DATA:僅讀取資料,不修改MODIFIES SQL DATA:會修改資料 (函數不支援)CONTAINS SQL:包含 SQL 但不讀寫資料若未宣告,MySQL 拒絕建立,除非開啟 log_bin_trust_function_creators 信任建立者。
mysql> SET GLOBAL log_bin_trust_function_creators = 1; # 或 mysql> SET GLOBAL log_bin_trust_function_creators = ON; # 驗證 mysql> SHOW VARIABLES LIKE 'log_bin_trust_function_creators'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | log_bin_trust_function_creators | ON | +---------------------------------+-------+
my.cnf / my.ini:
[mysqld] log_bin_trust_function_creators = 1 # 5.7+ 也可用 log_bin_trust_routine_creators = 1
修改後執行 systemctl restart mysqld 或 net restart mysql。
CREATE FUNCTION `fn_calc_total`(price DECIMAL(10,2), qty INT)
RETURNS DECIMAL(10,2)
DETERMINISTIC
NO SQL
BEGIN
RETURN price * qty;
END;
DETERMINISTIC:告知優化器相同參數結果固定,可啟用查詢快取。NO SQL / READS SQL DATA:視函數內容誠實宣告。SELECT 查表,需用 READS SQL DATA。| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 全域 SET GLOBAL | 即時生效、無需重啟 | 重啟失效、降低複制安全性 | 開發/測試環境、臨時急救 |
| 配置檔永久 | 永久生效 | 需重啟、降低複制安全性 | 內部系統、可接受風險 |
| 函數宣告特徵 | 最安全、符合規範、利於優化 | 需逐個函數修改 | 生產環境強烈建議 |
TRIGGER、EVENT 建立。SHOW CREATE FUNCTION fn_calc_total\G # 輸出中會顯示: DETERMINISTIC, NO SQL 等特徵
SET GLOBAL log_bin_trust_function_creators=1 快速解決。DETERMINISTIC / READS SQL DATA 宣告。
3. 生產環境:關閉 log_bin_trust_function_creators,強制開發者遵守規範。
4. 文件化:建立函數建立規範清單,Code Review 時檢查。
遵循「明確宣告 > 信任建立者」原則,兼顧複制安全與開發效率。