error 1418 根本原因是开启 binlog 后未声明函数的 deterministic、no sql 或 reads sql data 属性,mysql 为保障主从一致性强制校验;可通过 set global 或配置文件启用 log_bin_trust_function_creators=1 临时或永久绕过,但推荐显式声明函数特性以确保安全与可维护性。

MySQL 自定义函数报错 ERROR 1418,根本原因是开启了二进制日志(log_bin=ON)但未显式声明函数的确定性或安全属性,MySQL 为防止主从不一致而拒绝创建——这不是权限问题,也不是语法错误,而是复制安全机制的强制校验。
为什么开启 binlog 后必须设置 log_bin_trust_function_creators
当 log_bin=ON 时,MySQL 要求所有自定义函数满足以下至少一项:
- 声明为
DETERMINISTIC(输入相同则输出必相同) - 声明为
READS SQL DATA或NO SQL - 被标记为可信:即
log_bin_trust_function_creators=ON
否则直接报 ERROR 1418: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled。默认值是 OFF,所以只要开了 binlog(常见于生产环境、主从架构),几乎必踩这个坑。
临时绕过:用 SET 命令启用信任(会话级)
适合开发调试或单次执行,不持久,重启或新连接失效:
SET GLOBAL log_bin_trust_function_creators = 1;
注意:GLOBAL 需要 SYSTEM_VARIABLES_ADMIN 或 SUPER 权限;普通用户即使有 CREATE ROUTINE 也不行。如果提示权限不足,得找 DBA 执行。
永久生效:修改 my.cnf 并重启 MySQL
在配置文件(如 /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf)的 [mysqld] 段下添加:
log_bin_trust_function_creators=1
然后重启服务:systemctl restart mysql(或 mysqld)。这比每次 SET 更可靠,但要注意:它让所有用户都能创建无显式特性的函数,属于“放宽复制安全边界”,仅建议在可控环境(如内部测试库、已确认函数行为稳定)中启用。
更安全的做法:显式声明函数特性(推荐)
不依赖全局开关,而是写函数时就明确标注,既通过校验,又提升可读性和可维护性:
CREATE FUNCTION my_add(a INT, b INT) RETURNS INT DETERMINISTIC BEGIN RETURN a + b; END
关键点:
-
DETERMINISTIC:适用于纯计算、不查表、不调用非确定函数(如NOW()、RAND()) -
READS SQL DATA:只读查询,不修改数据(如SELECT COUNT(*) FROM t) -
MODIFIES SQL DATA:会写入或删除数据(此时即使设了 trust,也可能被 binlog 拒绝,因涉及事务一致性) - 避免混用
NOT DETERMINISTIC和READS SQL DATA—— 这类函数在 statement-based 复制下极易导致主从偏差
真正容易被忽略的是:即使设置了 log_bin_trust_function_creators=1,如果函数内部用了 INSERT/UPDATE/DELETE 或临时表,仍可能在主从切换或备份恢复时出问题——安全不是靠开关,而是靠设计本身是否可重现。











