MySQL函数与触发器权限需显式授予:CREATE/ALTER ROUTINE控制函数创建修改,TRIGGER权限须表级授权,EXECUTE控制函数执行,跨库调用需目标库表对应权限,且权限变更后需FLUSH PRIVILEGES或重连生效。

CREATE ROUTINE 和 ALTER ROUTINE 权限控制函数创建与修改
MySQL 中创建或修改存储函数(CREATE FUNCTION)必须显式授予 CREATE ROUTINE 权限;若要修改已有函数,则还需 ALTER ROUTINE。这两个权限默认只赋予 root 或具备 GRANT OPTION 的高权限账号,普通用户即使有数据库级 SELECT/INSERT 权限也无法绕过。
-
CREATE ROUTINE是创建函数/存储过程的前提,不包含执行权 -
ALTER ROUTINE用于ALTER FUNCTION或DROP FUNCTION,但不能仅靠它创建新函数 - 若启用
log_bin_trust_function_creators=OFF(默认),还必须额外授予EXECUTE权限才能让函数被二进制日志接受,否则报错:This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration
GRANT CREATE ROUTINE, ALTER ROUTINE ON `mydb`.* TO 'devuser'@'localhost'; FLUSH PRIVILEGES;
TRIGGER 权限需单独授权且作用于表级别
触发器(CREATE TRIGGER)权限不继承自数据库或全局权限,必须在具体表上授予 TRIGGER 权限。即使用户对某张表有 ALL PRIVILEGES,若未显式给 TRIGGER,仍会报错:ERROR 1227 (42501): Access denied; you need (at least one of) the SUPER or TRIGGER privilege(s) for this operation。
- 触发器定义语句中引用的其他表,调用者还需具备对应表的
SELECT或UPDATE权限(取决于触发器逻辑) - 删除触发器(
DROP TRIGGER)同样需要该表上的TRIGGER权限 - 注意:MySQL 8.0+ 中
SUPER权限已被拆解,TRIGGER不再隐含在SYSTEM_VARIABLES_ADMIN等新权限中
GRANT TRIGGER ON `mydb`.`orders` TO 'appuser'@'%'; GRANT SELECT, UPDATE ON `mydb`.`logs` TO 'appuser'@'%'; -- 若触发器里 INSERT INTO logs
函数执行权限(EXECUTE)和跨库调用的权限链问题
函数定义完成后,调用它需要目标函数上的 EXECUTE 权限。这个权限可以按函数名精确授予,也可以用 * 授予整个库下所有函数。但要注意:如果函数体内访问了其他数据库的表,MySQL 会检查当前用户对该库表的实际权限,而不是“是否能调用函数”这一层。
- 授予函数执行权:
GRANT EXECUTE ON FUNCTION mydb.calc_tax TO 'reporter'@'localhost'; - 跨库查询失败常见于函数内写死
otherdb.sales,但用户没有otherdb的SELECT权限——此时报错不是权限不足于函数,而是Table 'otherdb.sales' doesn't exist或Access denied - 避免使用
SQL SECURITY DEFINER+ 高权限 definer 账号来绕过权限检查,这会带来安全隐患和审计盲区
SHOW CREATE FUNCTION mydb.calc_tax; -- 检查其 SQL SECURITY 是 DEFINER 还是 INVOKER
权限生效与调试关键点
MySQL 权限变更后不会自动刷新到活跃连接,必须执行 FLUSH PRIVILEGES(仅当直接操作 mysql 系统表时才强制需要);但更稳妥的做法是让应用重建连接,或确认当前会话已重新认证。调试时最容易忽略的是主机名匹配规则和匿名用户干扰。
- 检查权限是否命中:
SHOW GRANTS FOR 'user'@'host';,注意'user'@'%'和'user'@'192.168.1.%'是不同主体 - 匿名用户(
''@'localhost')可能意外覆盖你的显式授权,用SELECT User, Host FROM mysql.user;排查 - 函数/触发器创建失败时,先确认
log_bin_trust_function_creators值,再查SELECT @@log_bin;是否启用了 binlog
SELECT @@log_bin_trust_function_creators, @@log_bin;
实际设权时最常卡在「以为给了库权限就等于给了函数权限」,或者「触发器建在 A 表,却忘了函数里查的 B 表没授权」。权限颗粒度比想象中细,得一层层对着错误信息反推缺哪一环。










