mysql 5.7 不支持 grant execute on procedure,会报 error 1064;8.0.16+ 才支持,但必须先授 usage 权限且数据库名、过程名须完整精确,否则静默失效。

GRANT EXECUTE ON PROCEDURE 语法是否生效,取决于 MySQL 版本
MySQL 5.7 不识别 GRANT EXECUTE ON PROCEDURE db.proc_name 写法,执行直接报错 ERROR 1064 (42000);只有 8.0.16+ 才真正支持该语法,但必须满足两个硬性前提:
- 先执行
GRANT USAGE ON `db_name`.* TO 'user'@'host'—— 缺这步,后续授权会静默失败(无报错,但权限不生效) - 数据库名和过程名必须完整、精确:
GRANT EXECUTE ON PROCEDURE mydb.calc_score TO 'dev'@'%'合法;GRANT EXECUTE ON PROCEDURE calc_score TO ...或GRANT EXECUTE ON PROCEDURE mydb.*均非法
CALL 报 ERROR 1370 不一定没给 EXECUTE 权限
更常见的情况是:EXECUTE 已授,但过程内部 SQL 的权限校验失败。关键看 SQL SECURITY 设置:
- 默认
SQL SECURITY DEFINER:过程以定义者身份执行,若定义者账号(如'dba'@'localhost')已被删或权限回收,CALL就会报ERROR 1370 -
SQL SECURITY INVOKER:过程内所有操作都校验调用者权限——此时光有EXECUTE不够,还得单独给调用者SELECT ON mydb.users这类表级权限 - 查定义用
SHOW CREATE PROCEDURE mydb.proc_name,重点关注DEFINER和SQL SECURITY字段
只让开发者能 CALL,不能看源码或改过程
EXECUTE 权限本身不包含查看定义能力。想做到“仅执行、不暴露”,要同时控制两件事:
- 只授
EXECUTE ON PROCEDURE db.proc_name,不授ALTER ROUTINE—— 否则用户可用SHOW CREATE PROCEDURE看明文逻辑,甚至DROP PROCEDURE - 避免用
GRANT SELECT ON mysql.proc或INFORMATION_SCHEMA.ROUTINES替代 —— 这会让用户看到所有库的过程名和定义,严重越权 - 验证是否真生效,别信
SHOW GRANTS(它在 routine 级授权下常不显示),直接CALL db.proc_name()测试
主机名匹配错误是最隐蔽的权限失效原因
MySQL 把 'user'@'%' 和 'user'@'localhost' 视为完全不同的账号,权限不互通。排查时务必确认:
- 用户实际连接用的是什么 host:
SELECT USER(), CURRENT_USER();—— 前者是客户端声明的身份,后者才是 MySQL 实际匹配的账号 - 检查账号是否存在:
SELECT Host, User FROM mysql.user WHERE User = 'dev'; - 授权时写的 host 必须和
CURRENT_USER()返回的完全一致,哪怕只是'dev'@'127.0.0.1'和'dev'@'localhost'的差别
真正难控的不是“能不能 CALL”,而是“CALL 之后到底以谁的身份查哪张表”。DEFINER 模式省事但提权风险高,INVOKER 模式安全但要求 DBA 配合重建过程——权限落地前,得先理清这一层。











