mysql 8.0.16+才支持grant execute on procedure语法,5.7及更早版本执行即报error 1064;必须先授usage权限且过程名须带库名,缺一不可。

GRANT EXECUTE ON PROCEDURE 语法是否生效取决于 MySQL 版本
MySQL 5.7 及更早版本根本不识别 GRANT EXECUTE ON PROCEDURE db.proc_name,执行直接报 ERROR 1064;只有 8.0.16+ 才真正支持该语法,且必须满足两个硬性前提:
- 先执行
GRANT USAGE ON `db`.* TO 'user'@'%'(不能省略数据库名,也不能用mydb.*替代过程名) - 过程名必须带库名,
GRANT EXECUTE ON PROCEDURE calc_score是非法的,必须写成GRANT EXECUTE ON PROCEDURE mydb.calc_score - 通配符不适用:
GRANT EXECUTE ON PROCEDURE mydb.*会报错,这不是合法语法
EXECUTE 权限 ≠ 表级访问权限,DEFINER 才是关键瓶颈
即使 GRANT EXECUTE 成功,CALL mydb.sync_data() 仍可能报 ERROR 1370 (42000): execute command denied。这不是授权没生效,而是过程内部 SQL 在运行时权限校验失败:
- 默认
SQL SECURITY DEFINER,所有语句以DEFINER账号身份检查权限 —— 查看定义:SHOW CREATE PROCEDURE mydb.sync_data,确认DEFINER字段是否指向一个已失效或权限不足的账号 - 过程里用了跨库表(如
other_db.users),但DEFINER对那个库没有 SELECT 权限 - 连接主机名不匹配:授权是
'dev'@'10.0.1.%',但实际连接用的是'dev'@'localhost',MySQL 视为不同用户
为什么 REVOKE 单个过程权限无效
MySQL 的 EXECUTE 权限继承自数据库层级。只要用户有 mydb.* 的 EXECUTE 权限,显式执行 REVOKE EXECUTE ON PROCEDURE mydb.sp_x FROM 'u'@'%' 不会起作用 —— 这不是 bug,是设计逻辑。
-
REVOKE EXECUTE ON PROCEDURE在 MySQL 中基本无意义,它不会影响调用能力 - 想真正限制某个过程,只能:
REVOKE EXECUTE ON mydb.* FROM 'u'@'%'(收回整个库的执行权),再对其他过程逐个GRANT EXECUTE ON PROCEDURE - 或者让过程使用
SQL SECURITY INVOKER,使权限校验落在调用者身上(但需 DBA 用ALTER PROCEDURE修改,普通用户无此权限)
只给 EXECUTE 就够了?别漏掉 USAGE 和 FLUSH
很多人卡在“明明授了 EXECUTE,CALL 还是失败”,往往是因为跳过了基础步骤:
- 必须先
GRANT USAGE ON `mydb`.* TO 'dev'@'%'—— 这步不报错、不提示,但缺了它,后续GRANT EXECUTE ON PROCEDURE会静默失效 - 常规
GRANT语句通常自动生效,但若你之前手动改过mysql.procs_priv或用旧方式授权,务必执行FLUSH PRIVILEGES - 验证不要只信
SHOW GRANTS:它在 routine 级授权下有时不显示EXECUTE,最可靠方式是直接CALL mydb.get_user_summary()
真正难控制的不是“能不能调用”,而是“调用时查哪张表、以谁的身份查”。SQL SECURITY 设置才是权限边界的开关,不碰它,光调权限只是隔靴搔痒。











