ERROR 1418 是 MySQL 开启 binlog 后强制校验函数声明所致,必须按实际行为选择 DETERMINISTIC、NO SQL 或 READS SQL DATA;误用 DETERMINISTIC 可致主从不一致,SET GLOBAL log_bin_trust_function_creators=1 仅为临时绕过,非根本解法。

ERROR 1418 是 binlog 安全校验,不是权限或语法问题
报错 ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled 的根本原因,是 MySQL 在 log_bin=ON(即开启二进制日志)时,强制要求每个函数必须显式声明其行为特性——它不是你写错了 SQL,也不是缺 CREATE ROUTINE 权限,而是复制安全机制在拦截。
常见误解是“加个 DETERMINISTIC 就行”,但若函数实际读表却硬加 DETERMINISTIC,会导致主从数据不一致,比报错更危险。
必须按函数真实行为选对特性子句
函数体里到底干了什么,决定了该用哪个声明:
- 只做字符串/数学运算、不碰数据库 → 用
DETERMINISTIC或NO SQL(推荐后者,语义更准) - 执行了
SELECT查询(哪怕只查一张表)→ 必须用READS SQL DATA - 用了
INSERT/UPDATE/DELETE→ 函数不允许在 binlog 开启时创建(MySQL 不支持MODIFIES SQL DATA用于函数) - 调用了
NOW()、RAND()等函数 → 仍可声明DETERMINISTIC,因为 MySQL 会把时间戳/随机种子一并写入 binlog,保证主从执行结果一致
错误示例:CREATE FUNCTION get_user_name(id INT) RETURNS VARCHAR(50) BEGIN RETURN (SELECT name FROM users WHERE id = id); END —— 没声明 READS SQL DATA,必报 1418。
SET GLOBAL log_bin_trust_function_creators = 1 是临时补丁,不是解法
执行 SET GLOBAL log_bin_trust_function_creators = 1 能绕过校验,但它只是关闭安全检查,并不解决函数本身是否适合复制的问题:
- 需要
SYSTEM_VARIABLES_ADMIN或SUPER权限,普通开发账号通常没有 - 仅对当前会话生效,MySQL 重启后失效
- 生产环境禁用:一旦函数行为与声明不符,主从数据就可能错位
- 配置文件永久启用需在
[mysqld]下加log-bin-trust-function-creators=1,但依然不推荐
它只适合本地调试或一次性导入脚本,不能作为上线方案。
最容易被忽略的细节:DELIMITER 和函数体空格
即使特性声明写对了,也可能因格式问题失败:
-
DETERMINISTIC必须紧贴RETURNS后面,中间不能换行或多余空格(如RETURNS VARCHAR(10) \n DETERMINISTIC可能被解析失败) - 必须用
DELIMITER $$切换结束符,否则 MySQL 会在第一个;就截断函数定义 - 函数名含数据库名时(如
mydb.myfunc),确保当前用户对该库有CREATE ROUTINE权限,而不仅是SELECT
真正安全的做法,是先确认函数逻辑,再选最匹配的特性子句,最后用标准语法创建。别让 1418 成为掩盖函数设计缺陷的遮羞布。


















