MySQL 5.7自定义函数失效主因是DEFINER用户缺失、权限不足(含SYSTEM_VARIABLES_ADMIN)或引用已删库表;须先用SHOW CREATE FUNCTION查DEFINER和SQL SECURITY,再验证用户存在性、跨库权限及log_bin_trust_function_creators状态。

MySQL 5.7 中自定义函数“损坏”或“失效”,90% 不是代码逻辑错,而是 DEFINER 用户缺失、权限不全,或函数体引用了已删库/表导致元数据不一致——直接 DROP FUNCTION 再重装常失败,得先查清定义来源和依赖关系。
查清函数的 DEFINER 和实际执行上下文
函数报错(如 ERROR 1418、ERROR 1370)时,SHOW CREATE FUNCTION func_name 返回的 DEFINER 值往往已失效。重点看两行:
-
DEFINER=`some_user`@`host`:若该用户在mysql.user表中查不到(SELECT User, Host FROM mysql.user WHERE User = 'some_user'),函数就无法加载 -
SQL SECURITY DEFINER(默认):函数以 DEFINER 身份运行,不是调用者;若没写这句,MySQL 就按此模式执行 - 若函数里读了系统变量(如
@@version),DEFINER 还必须有SYSTEM_VARIABLES_ADMIN权限(MySQL 5.7.20+ 引入,非SUPER)
修复 DEFINER 用户权限而非改 SQL SECURITY
别急着把函数改成 SQL SECURITY INVOKER——这会让每个调用者都得单独授权,运维成本爆炸。正确路径是让 DEFINER “复活”并补权:
- 用 root 登录,执行
CREATE USER 'some_user'@'host' IDENTIFIED BY 'pwd';(若用户不存在) - 授最小必要权限:
GRANT SELECT ON your_db.your_table TO 'some_user'@'host';(函数里查哪张表就授哪张) - 若跨库查询(如
SELECT * FROM audit_log.events),必须对audit_log库也授权 - 若函数含
SELECT @@sql_mode等语句,补上:GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'some_user'@'host'; - 执行
FLUSH PRIVILEGES;后立刻测试:SELECT func_name();
函数体引用的表或列已不存在怎么办?
函数定义本身能查到,但调用时报 “Table doesn’t exist” 或 “Unknown column”,说明函数体硬编码了已删对象。此时 ALTER FUNCTION 不可用(MySQL 5.7 不支持修改函数体),只能重建:
- 先用
SHOW CREATE FUNCTION func_name备份原定义(注意复制整段,含DELIMITER $$和结尾$$) - 检查函数 SQL 体内所有表名、列名是否真实存在:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='your_db'; - 若表已删,且业务允许,可临时重建空表(
CREATE TABLE missing_table (id INT) ENGINE=InnoDB;)再导入函数 - 若列名改过(如
user_name→username),必须手动修改函数体中的字段引用,再DROP FUNCTION+CREATE FUNCTION - 重建后务必验证:函数内若有
CONCAT拼接表名/列名,属于高危设计,应尽快下线并移交应用层处理
为什么 DROP + CREATE 还是失败?
常见于 Docker 或云数据库环境,两个隐藏开关常被忽略:
-
log_bin_trust_function_creators必须为ON,否则即使有权限也无法创建函数(报 ERROR 1418)。检查:SELECT @@log_bin_trust_function_creators;,设为 1:SET GLOBAL log_bin_trust_function_creators = 1; - 函数若含
READS SQL DATA或MODIFIES SQL DATA,DEFINER 必须有对应权限,不能只靠SELECT;例如含UPDATE就要补UPDATE权限 - Mac Homebrew 环境下,
/usr/local/var/mysql/目录属主可能不是mysql,导致函数加载时读取.frm失败,执行sudo chown -R mysql:mysql /usr/local/var/mysql
最易被忽略的一点:函数定义里的字符集声明(如 CHARSET utf8mb4)若与当前库不一致,MySQL 5.7 会静默跳过加载,SHOW FUNCTION STATUS 里看不到该函数——必须比对 SHOW CREATE DATABASE your_db 的默认字符集,确保函数体中所有字符串字面量和参数声明匹配。


















