根本原因是mysql开启binlog后强制校验函数安全性,普通用户需显式声明deterministic/no sql/reads sql data特性,或由dba设置log_bin_trust_function_creators=1方可创建。

非 Super 用户默认无法创建存储函数,根本原因不是权限缺失,而是 MySQL 的二进制日志(binlog)安全机制在拦截——它要求函数必须明确声明行为特性,或全局放宽信任策略。
为什么普通用户执行 CREATE FUNCTION 会报错 “You do not have the SUPER privilege…”
这个错误通常出现在启用了 binlog(log_bin = ON)的 MySQL 实例上。即使你已授予 CREATE ROUTINE 权限,MySQL 仍会检查 log_bin_trust_function_creators 变量是否为 1。默认是 0,此时只有拥有 SUPER 权限的用户才能创建函数,否则直接拒绝。
常见错误信息:You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
- 该限制与复制环境强相关:防止不确定函数在主从间产生不一致
- 哪怕你没配主从,只要
log_bin开着(例如开启了备份、审计或监控工具依赖 binlog),就触发此检查 -
SELECT @@log_bin可确认是否启用 binlog;SELECT @@log_bin_trust_function_creators查当前值
两种合法绕过方式:改变量 or 补特性声明
推荐优先使用「补特性声明」,更安全、无需重启、不依赖全局配置变更。
创建函数时必须显式指定至少一个 characteristic,且不能只写 NOT DETERMINISTIC(这是默认值,无效)。有效组合包括:
-
DETERMINISTIC:函数对相同输入必返回相同结果(如ABS()、UPPER()) -
NO SQL:函数体内完全不访问数据库(如纯计算、字符串拼接) -
READS SQL DATA:只读表,不修改(如SELECT name FROM user WHERE id = ?) -
MODIFIES SQL DATA:会写入或删除数据(极少用于函数,更推荐用存储过程)
示例(合法):
CREATE FUNCTION get_user_name(uid INT) RETURNS VARCHAR(50) READS SQL DATA BEGIN DECLARE name_out VARCHAR(50); SELECT name INTO name_out FROM users WHERE id = uid; RETURN name_out; END;
错误写法(仍被拒):
CREATE FUNCTION bad_func(x INT) RETURNS INT NOT DETERMINISTIC -- 单独这一行不够,必须搭配 NO SQL / READS SQL DATA 等 BEGIN RETURN x + RAND(); END;
设置 log_bin_trust_function_creators = 1 的实操要点
若必须用此方式(例如开发环境快速验证),注意它不是“开个开关”那么简单:
- 需要
SUPER权限才能执行SET GLOBAL log_bin_trust_function_creators = 1—— 所以首次仍需 DBA 或 root 操作 - 该变量是动态的,但仅对新连接生效;已有连接不受影响
- 永久生效需写入配置文件:
[mysqld]段下加log_bin_trust_function_creators = 1,然后重启mysqld - ⚠️ 不要仅靠
SET SESSION:该变量不支持 session 级别设置
顺便一提:binlog_format 建议设为 MIXED 或 ROW,避免 STATEMENT 格式下因函数不确定性导致复制失败。
授权环节容易漏掉的关键权限和 DEFINER 问题
即使函数创建成功,普通用户也可能调用失败,常见于以下两点:
- 只授了
CREATE ROUTINE,但忘了EXECUTE权限:GRANT EXECUTE ON testdb.* TO 'user'@'%' - 函数由
root@localhost创建,默认DEFINER = 'root'@'localhost',而普通用户无权读取mysql.proc或执行定义者上下文操作;解决方法是创建时显式指定SQL SECURITY INVOKER,或让目标用户自己创建函数 - 若函数内查了系统表(如
information_schema),还需确保该用户有对应库表的SELECT权限
最稳妥的做法:让业务用户用自己的账号登录,直接创建、调用函数,全程不依赖 root 账号介入。











