只给execute权限即可调用存储过程,但必须精确到procedure db_name.proc_name,且仅mysql 8.0.16+支持该语法;5.7及更早版本执行即报error 1064。

只给 EXECUTE 权限就能让用户调用存储过程,但必须精确到 PROCEDURE db_name.proc_name,且 MySQL 8.0.16+ 才真正支持该语法;5.7 及更早版本执行 GRANT EXECUTE ON PROCEDURE ... 会直接报 ERROR 1064。
MySQL 版本决定 GRANT EXECUTE ON PROCEDURE 能不能用
MySQL 5.7 不识别 GRANT EXECUTE ON PROCEDURE mydb.p1 这种写法,一执行就报错;8.0.16+ 才正式支持,但有硬性前提:
- 必须先授予数据库级
USAGE权限:GRANT USAGE ON `mydb`.* TO 'dev'@'%' - 数据库名不能省略:
GRANT EXECUTE ON PROCEDURE p1是错的,必须写全mydb.p1 - 过程名不能用通配符:
GRANT EXECUTE ON PROCEDURE mydb.*是非法语法 - 如果想授整个库下所有 routine(含函数),可用
GRANT EXECUTE ON mydb.*,但这不是“仅过程”
CALL 失败却已授 EXECUTE?大概率是 SQL SECURITY 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字段,若为'dba'@'localhost',而该账号已被删或权限回收,过程就失效 - 过程里用了跨库表(如
other_db.users),但DEFINER对那个库没权限 - 连接主机名不匹配:授权是
'dev'@'10.20.30.%',实际连的是'dev'@'localhost',MySQL 视为不同用户
只想让开发者能 CALL,但不能看、不能改、不能删
这是最常见也最容易被误配的场景:
- 只给
EXECUTE:允许CALL,但SHOW CREATE PROCEDURE报错 —— 正常,因为查看定义需要ALTER ROUTINE - 别给
ALTER ROUTINE:它包含查看、修改、删除能力,普通开发者不需要,给了等于暴露逻辑甚至可篡改 - 别用
GRANT SELECT ON mysql.proc或INFORMATION_SCHEMA.ROUTINES替代:这会让用户看到所有库的过程定义,严重越权 - 验证是否生效,最可靠方式是直接测试:
CALL mydb.get_user_summary(),而不是依赖SHOW GRANTS(它在某些粒度下根本不显示EXECUTE)
真正难控的不是“能不能 CALL”,而是“CALL 之后查哪张表、以谁的身份查”
权限分离的终点不是授不授 EXECUTE,而是过程运行时的数据访问边界。哪怕你把 SQL SECURITY 改成 INVOKER,让权限校验落在调用者身上,也需要重建过程 —— 而重建又需要 ALTER ROUTINE 权限,普通开发者通常没有。最终,这事绕不开 DBA 配合改定义。











