必须显式授予execute权限,且语法必须为grant execute on procedure db_name.proc_name to 'user'@'host';缺库名、用通配符、省略procedure或误写为function均失败,mysql 5.7不支持过程级授权,8.0.16+才稳定支持该语法。

必须显式授予 EXECUTE 权限,且语法中 PROCEDURE 关键字和完整 db_name.proc_name 格式缺一不可;漏掉数据库名、用通配符或省略 PROCEDURE 都会失败。
GRANT EXECUTE ON PROCEDURE 语法必须带库名和过程名
MySQL 不接受模糊写法。常见错误包括:GRANT EXECUTE ON myproc TO ...(缺库名)、GRANT EXECUTE ON mydb.* TO ...(范围过大)、GRANT EXECUTE ON *.* TO ...(非法对象类型)。
正确写法只有一种形式:
GRANT EXECUTE ON PROCEDURE `mydb`.`calc_score` TO 'app_user'@'10.20.%';
- 反引号
`在库名或过程名含下划线、数字开头或为保留字时必须保留,否则解析失败 - 不能用
GRANT EXECUTE ON FUNCTION替代——函数和过程权限独立,互不覆盖 - MySQL 5.7 不支持
GRANT EXECUTE ON ALL PROCEDURES IN DATABASE这类语法(那是 MySQL 8.0.26+ 才加的)
调用时仍报 EXECUTE command denied?检查 DEFINER 和 SQL SECURITY
即使 GRANT EXECUTE 成功,CALL mydb.calc_score() 仍可能报错,大概率是过程定义里的执行上下文不匹配。
查定义:
SHOW CREATE PROCEDURE `mydb`.`calc_score`;
重点关注两处:
-
DEFINER:如为'dba'@'%',则执行时以该账号权限检查底层表(比如SELECT FROM mydb.users) -
SQL SECURITY:默认是DEFINER,即“按定义者权限跑”;若调用者app_user对mydb.users无SELECT权限,就会被拒
解决方法只有重建过程并指定 SQL SECURITY INVOKER:
CREATE PROCEDURE `mydb`.`calc_score`() SQL SECURITY INVOKER BEGIN SELECT COUNT(*) FROM users; END;
注意:普通用户没有 ALTER ROUTINE 权限,需 DBA 操作。
用户在 Navicat/SQLyog 看不到存储过程定义?补 SELECT on mysql.proc
工具连上后看不到过程列表或点不开“查看定义”,不是权限没给,而是缺少元数据读取权限。
MySQL 5.7 中,SHOW CREATE PROCEDURE 依赖 mysql.proc 表,而该表默认只对 super 用户开放。
临时方案(仅限 5.7):
GRANT SELECT ON mysql.proc TO 'app_user'@'10.20.%';
- ⚠️ 风险:该授权会让用户看到所有数据库所有过程的定义(包括没权限访问的库),生产环境慎用
- 不解决执行问题,只解决“看定义”需求;执行仍需单独
GRANT EXECUTE ON PROCEDURE ... - MySQL 8.0+ 已弃用
mysql.proc,改用INFORMATION_SCHEMA.ROUTINES,但该视图在 8.0+ 中自动过滤——用户只能看到自己有权限的 routine,无需额外授权
真正容易被忽略的是:权限生效不等于过程能跑通。EXECUTE 授权只是“准许调用入口”,过程内部每条 SQL 的权限都得单独满足——尤其是当它查其他库的表、写日志表、或调用另一个未授权的过程时,都会在运行时报错,而不是在 CALL 时就拒绝。











