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)
啟用 log_bin 時,MySQL 強制要求創建的函數/存儲過程/觸發器必須聲明以下特性之一,確保主從同步時行為確定性:
| 聲明特性 | 含義 | 適用場景 |
|---|---|---|
| DETERMINISTIC | 相同輸入必產生相同輸出 | 純計算函數、格式化轉換 |
| NO SQL | 不包含任何 SQL 語句 | 純邏輯計算、字符串處理 |
| READS SQL DATA | 只讀數據,不修改 | 查詢類函數、統計聚合 |
| MODIFIES SQL DATA | 修改數據 (函數不支援) | 存儲過程專用 |
| CONTAINS SQL | 包含 SQL 但不讀寫數據 (默認) | 不滿足上述任一條件 |
函數僅支援前三種聲明;存儲過程支援全部五種。未聲明默認為 CONTAINS SQL,觸發 1418 錯誤。
-- 確定性函數
CREATE FUNCTION hello(s CHAR(20))
RETURNS CHAR(50)
DETERMINISTIC
RETURN CONCAT('hello ', s, '!');
-- 只讀數據函數
CREATE FUNCTION get_cid(n CHAR(20))
RETURNS INT
READS SQL DATA
BEGIN
RETURN (SELECT cid FROM stu WHERE sname = n);
END;
CREATE PROCEDURE transfer(IN from_id INT, IN to_id INT, IN amount DECIMAL(10,2))
MODIFIES SQL DATA
BEGIN
UPDATE account SET balance = balance - amount WHERE id = from_id;
UPDATE account SET balance = balance + amount WHERE id = to_id;
END;
CREATE TRIGGER audit_log
AFTER UPDATE ON account
FOR EACH ROW
BEGIN
-- 觸發器隱含 READS SQL DATA,但建議顯式聲明存儲過程特性
INSERT INTO audit_log (account_id, old_balance, new_balance)
VALUES (OLD.id, OLD.balance, NEW.balance);
END;
SET GLOBAL log_bin_trust_function_creators = 1;
mysqld --log-bin-trust-function-creators=1
# /etc/my.cnf [mysqld] log_bin_trust_function_creators = 1
安全警告:開啟此選項允許創建不確定性函數,可能導致主從數據不一致。生產環境強制要求方案一,嚴禁長期開啟信任模式。
SHOW VARIABLES LIKE 'log_bin_trust_function_creators'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | log_bin_trust_function_creators | ON | +---------------------------------+-------+
官方文檔明確:
NOW():binlog 記錄時間戳,從庫重放時使用相同時間戳,視為確定性輸入RAND():單次調用種子同步,視為確定性因此包含 NOW()/RAND() 的函數仍可聲明 DETERMINISTIC,無需因動態函數而放棄聲明。
ERROR 1418 是 MySQL 為保障主從一致性設置的守門機制。標準流程:
DETERMINISTIC/READS SQL DATA/MODIFIES SQL DATA)log_bin_trust_function_creators,用完即關