必须显式授予execute权限,且粒度精确到procedure db_name.proc_name;省略库名或使用mydb.*均错误,正确语法为grant execute on procedure mydb.proc_name to 'user'@'host'。

必须显式授予 EXECUTE 权限,且对象粒度精确到 PROCEDURE db_name.proc_name —— 给整个库或用 ALL PRIVILEGES 都是错的,既不安全也不符合最小权限原则。
GRANT EXECUTE ON PROCEDURE 语法必须带数据库名和过程名
MySQL 不支持只写 GRANT EXECUTE ON myproc 或 GRANT EXECUTE ON *.* 这类模糊写法。省略数据库名会报错 ERROR 1044 (42000): Access denied for user;只写库名(如 mydb.*)则授权的是该库下所有存储过程,不是“特定”过程。
- 正确写法:
GRANT EXECUTE ON PROCEDURE `mydb`.`calc_user_score` TO 'app_user'@'10.20.%'; - 错误写法:
GRANT EXECUTE ON calc_user_score TO ...(缺库名) - 错误写法:
GRANT EXECUTE ON mydb.* TO ...(范围过大,非“特定”) - 注意反引号:当库名或过程名含特殊字符或为关键字时,
`必须保留,否则可能解析失败
DEFINER 和 SQL SECURITY 决定实际执行时的权限上下文
即使 GRANT EXECUTE 成功,调用时仍可能报 EXECUTE command denied —— 很大概率是过程定义里的 DEFINER 账号权限过高,而 MySQL 默认按 SQL SECURITY DEFINER 执行,即以定义者身份检查底层表权限。
- 查定义:
SHOW CREATE PROCEDURE `mydb`.`calc_user_score`;看DEFINER和SQL SECURITY字段 - 若
DEFINER是'dba'@'%',但app_user对mydb.users表无SELECT权限,就会失败 - 解决方法:重建过程,加
SQL SECURITY INVOKER,让权限检查基于调用者:CREATE PROCEDURE ... SQL SECURITY INVOKER BEGIN ... - 重建需
ALTER ROUTINE权限,普通用户通常没有,得 DBA 操作
不能靠 SELECT mysql.proc 或 INFORMATION_SCHEMA.ROUTINES 替代 EXECUTE 授权
有人想绕过 EXECUTE 授权,直接给用户查 mysql.proc 或 INFORMATION_SCHEMA.ROUTINES 的权限来“看定义”,但这既不能执行过程,又带来严重越权风险。
-
GRANT SELECT ON mysql.proc TO ...→ 用户能读所有库所有过程定义,包括没权限访问的库 -
GRANT SELECT ON INFORMATION_SCHEMA.ROUTINES TO ...→ 同样全局可见,且 MySQL 8.0+ 中该表只返回当前用户有权限的 routine,但依然无法执行 -
ALTER ROUTINE虽可间接查看定义,但同时赋予删改权限,完全违背最小权限 - 真正需要“只读定义”场景,应由 DBA 定期导出并人工分发,而非开放系统表查询
权限生效不需要 FLUSH PRIVILEGES(除非你手改了 mysql.user 表)
用 GRANT 命令授完 EXECUTE 权限后,调用过程仍失败?先别急着 FLUSH PRIVILEGES —— MySQL 5.7.6+ 默认权限立即生效,这个命令只在你绕过 GRANT、直接 INSERT INTO mysql.tables_priv 等操作后才需要。
- 检查是否漏掉主机匹配:
'app_user'@'10.20.%'和实际连接的客户端 IP 是否吻合 - 确认过程确实存在于目标库:
SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'mydb' AND ROUTINE_NAME = 'calc_user_score'; - 确认用户已认证成功:
SELECT USER(), CURRENT_USER();—— 前者是登录账号,后者是权限匹配账号,二者不同常导致权限误判
最易被忽略的一点:EXECUTE 权限本身不依赖任何表级权限,但它背后的过程体如果访问了表,那些表的权限就得另算。也就是说,“能执行”和“执行不报错”是两回事 —— 后者取决于过程里每一条 SQL 在当前安全上下文下的实际权限。











