mysql不支持为只读用户精确授予查看单个存储过程定义的权限;8.0+中无view definition类权限,访问information_schema.routines需全局元数据权,grant select on mysql.proc在5.7越权、8.0已废弃,暴露全部过程逻辑且泄露definer敏感信息,违背只读与合规要求。

MySQL 不支持给只读用户“安全地”授予查看单个存储过程定义的权限。 你无法像 SQL Server 那样用 GRANT VIEW DEFINITION ON PROCEDURE 精确控制——MySQL 没有这个权限粒度,强行绕过会暴露全部过程逻辑,违背只读初衷。
为什么 SHOW CREATE PROCEDURE 会报错?
只读用户执行 SHOW CREATE PROCEDURE mydb.sp_name 报 ERROR 1305 (42000): PROCEDURE mydb.sp_name does not exist 或 ERROR 1370 (42000): execute command denied,不是因为没执行权,而是缺乏“查看定义”的元数据访问权限。MySQL 8.0+ 将过程定义存在 mysql.routines(不可直查),校验走的是 INFORMATION_SCHEMA.ROUTINES,而访问它需要额外权限。
别用 GRANT SELECT ON mysql.proc —— 5.7 兼容但严重越权
老方案 GRANT SELECT ON mysql.proc TO 'ro_user'@'%' 在 MySQL 5.7 可能“生效”,但它会让用户看到 所有数据库里所有存储过程的定义,包括你没授权访问的库(比如 sys、performance_schema 甚至其他业务库)。这等于把整个系统的逻辑结构白送出去。
- MySQL 8.0+ 已废弃
mysql.proc,该语句直接报错 - 即使在 5.7,用户还能通过
SELECT * FROM mysql.proc批量导出所有过程源码 - 只读用户本不该知道
other_db.cleanup_job这种过程的存在
MySQL 8.0+ 唯一合规路径:靠 DEFINER + USAGE + EXECUTE 组合绕行
如果你真需要让只读用户“间接看到”某个过程的逻辑,唯一可控方式是:确保该过程使用 SQL SECURITY INVOKER,且你已授予用户对目标库的 USAGE 和 EXECUTE 权限。这样用户调用时若失败,错误信息可能包含部分上下文(如表名),但仍不会返回完整定义。真正能看定义的,只有:
- 拥有
ALTER ROUTINE权限的用户(DBA 级别,远超只读) - 过程的
DEFINER账号本人(但只读用户显然不是) - root 或具备
SELECT权限的账号查INFORMATION_SCHEMA.ROUTINES(但这等于给了全局元数据读取权)
所以实际中,如果业务强依赖“只读用户可审计过程逻辑”,应在应用层或代理层(如 ProxySQL 规则)做日志/拦截,而不是在 MySQL 权限系统里硬凑。
最容易被忽略的一点
即便你设法让 SHOW CREATE PROCEDURE 对只读用户返回结果,它显示的 DEFINER 字段(如 DEFINER=`admin`@`10.0.1.%`)本身就是一个敏感信息——暴露了内部运维账号和网络段。很多合规审计(如等保、GDPR)明确禁止向非运维角色泄露这类元数据。











