MySQL 5.7不支持GRANT EXECUTE ON PROCEDURE语法,必须通过库级授权(GRANT EXECUTE ON db.*)结合专用过程库、显式回收SHOW ROUTINE和INFORMATION_SCHEMA.ROUTINES权限来逼近白名单效果,且需确保过程内所有SQL涉及的对象权限均被授予。

不能只靠 GRANT EXECUTE ON PROCEDURE 就让一个用户“安全地只执行某几个过程”——MySQL 原生不支持对象级白名单授权,必须结合版本、权限组合和结构设计才能逼近目标。
先确认 MySQL 版本是否支持精确授权
MySQL 5.7 及更早版本根本不识别 GRANT EXECUTE ON PROCEDURE db.sp_name 语法,执行会直接报错:ERROR 1064 (42000): You have an error in your SQL syntax。只有 8.0.16+ 才真正支持该语法,且必须满足两个硬性前提:
- 执行
SELECT VERSION();,确保返回值 ≥8.0.16 - 用户必须已显式创建(
CREATE USER 'u'@'%' IDENTIFIED BY 'p';),不能仅靠GRANT ... IDENTIFIED BY一步到位
8.0.16+ 必须先授 USAGE,否则静默失效
GRANT EXECUTE ON PROCEDURE mydb.p_calc 看似合法,但若没提前执行 GRANT USAGE ON `mydb`.* TO 'u'@'%',后续 CALL 仍会失败,且不报错、不提示,只在运行时暴露问题。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
-
USAGE是空权限占位符,必须带库名(mydb.*),不能省略或写成mydb - 过程名必须带库名:写
GRANT EXECUTE ON PROCEDURE p_calc非法;必须是GRANT EXECUTE ON PROCEDURE `mydb`.`p_calc` - 通配符不适用:
GRANT EXECUTE ON PROCEDURE mydb.*会报错,这不是合法语法
“EXECUTE command denied” 几乎从不因为没授 EXECUTE
这个错误极具误导性。真实卡点往往在运行时权限校验,比如:
- 过程定义为
SQL SECURITY DEFINER,但DEFINER='dba'@'localhost'已被删,MySQL fallback 到调用者权限,此时缺的是otherdb.users的SELECT权限,不是EXECUTE - 授权是
'u'@'10.0.1.%',但应用连的是'u'@'localhost'—— MySQL 视为两个账号,权限不共享 - 过程里用了
PREPARE/EXECUTE动态 SQL,MySQL 按调用者权限检查语句中涉及的表,此时SQL SECURITY INVOKER生效
5.7 中想逼近“只执行某几个过程”,只能靠隔离库 + 收权限
MySQL 5.7 不支持过程级授权,唯一可行路径是结构隔离:
- 把要开放的过程统一移到专用库(如
api_routines),再执行GRANT EXECUTE ON `api_routines`.* TO 'u'@'%' - 显式回收源码可见性:
REVOKE SHOW ROUTINE ON *.* FROM 'u'@'%'和REVOKE SELECT ON INFORMATION_SCHEMA.ROUTINES FROM 'u'@'%' - 绝对避免
GRANT EXECUTE ON *.*—— 全局授权无法撤销单个过程,且暴露全部 routine 结构
最容易被忽略的是:EXECUTE 权限本身不解决过程内部任何一条 SQL 的权限问题。哪怕所有语法、对象、host 全对,只要过程里一句 INSERT INTO log_table 缺权限,MySQL 就统一报 EXECUTE command denied,不会告诉你具体哪张表、哪条语句卡住。

















