MySQL 8.0.16+才支持GRANT EXECUTE ON PROCEDURE语法,5.7及更早版本执行即报ERROR 1064;必须先授USAGE权限、过程名须带库名,且'dev'@'localhost'与'dev'@'%'视为不同用户。

MySQL 8.0.16+ 才真正支持 GRANT EXECUTE ON PROCEDURE 语法;5.7 及更早版本执行即报 ERROR 1064,不是配置错,是压根不识别。
GRANT EXECUTE ON PROCEDURE 为什么总失败
最常踩的坑不是命令写错,而是漏掉前置条件或匹配偏差:
- 必须先执行
GRANT USAGE ON `mydb`.* TO 'dev'@'%'—— 这步不报错、不提示,但缺了它,后续GRANT EXECUTE ON PROCEDURE mydb.p1会静默失效 - 数据库名和过程名必须完整、精确:
GRANT EXECUTE ON PROCEDURE p1或GRANT EXECUTE ON PROCEDURE mydb.*都非法 -
'dev'@'localhost'和'dev'@'%'是两个完全独立的账号,权限不互通;用SELECT USER(), CURRENT_USER()确认实际匹配的是哪个 - MySQL 5.7 执行该语句直接报错,别试;升级前只能退而求其次:授
GRANT EXECUTE ON mydb.*(整个库所有 routine)
CALL 报 ERROR 1370 不代表没给 EXECUTE 权限
这个错误绝大多数时候和 EXECUTE 授权无关,而是过程运行时权限校验崩了:
- 查定义:
SHOW CREATE PROCEDURE mydb.sync_data,重点看DEFINER和SQL SECURITY - 默认
SQL SECURITY DEFINER:过程内所有 SQL 都以DEFINER账号身份检查权限 —— 若DEFINER='dba'@'localhost'已被删或权限回收,CALL就挂 - 若过程访问跨库表(如
other_db.users),DEFINER必须对那个库也有对应权限 - 改成
SQL SECURITY INVOKER可让权限校验落在调用者身上,但需重建过程,且普通用户无ALTER ROUTINE权限
只想让开发者能 CALL,不能看、不能改、不能删
这是生产环境最典型需求,但极易配错:
- 只授
EXECUTE ON PROCEDURE mydb.p1即可调用;SHOW CREATE PROCEDURE报错是正常表现,说明没暴露源码 - 绝对不要授
ALTER ROUTINE—— 它包含查看、修改、删除能力,给了等于交出逻辑控制权 - 别用
GRANT SELECT ON mysql.proc或INFORMATION_SCHEMA.ROUTINES替代 —— 这会让用户看到所有库所有过程定义,严重越权 - 验证是否真生效?直接
CALL mydb.p1()测试;SHOW GRANTS在 routine 级授权下常不显示,不可信
REVOKE 单个过程权限基本无效
MySQL 的 EXECUTE 权限继承自数据库层级,不是对象级原子控制:
-
REVOKE EXECUTE ON PROCEDURE mydb.p1 FROM 'u'@'%'不起作用 —— 这不是 bug,是设计如此 - 想限制某个过程,只能:先
REVOKE EXECUTE ON mydb.* FROM 'u'@'%',再对其他过程逐个GRANT EXECUTE ON PROCEDURE - 或者让过程用
SQL SECURITY INVOKER,把权限边界收束到调用者身上(仍需 DBA 重建过程)
真正难控的从来不是“能不能 CALL”,而是“CALL 之后,以谁的身份、查哪张表、有没有权限”。DEFINER 模式省事但风险隐蔽,INVOKER 安全但权限链更长——选哪个,得看你的数据边界是否清晰、DBA 是否愿意配合改定义。


















