explain报错“select command denied”主因是缺失show view权限,而非explain权限;该权限需在数据库级授予,且视图跨库或含definer时还需对应库select权及definer存在。

EXPLAIN 为什么报错“SELECT command denied”
运维人员执行 EXPLAIN 失败,90% 不是因为缺“EXPLAIN 权限”,而是 MySQL 在解析视图或复杂查询时,需要先展开底层定义——这个过程依赖 SHOW VIEW 权限。没有它,MySQL 看不到视图里查了哪些表,就直接拒绝执行,报错 ERROR 1142 (42000): SELECT command denied to user for table 'xxx'。
更关键的是:SELECT 权限 ≠ SHOW VIEW 权限。即使用户能 SELECT * FROM v_sales_summary,也可能无法 EXPLAIN v_sales_summary,因为前者只校验结果访问,后者要校验定义来源。
-
SHOW VIEW必须在数据库级别授予,例如GRANT SHOW VIEW ON app_db.* TO 'ops'@'192.168.5.%';写成ON app_db.v_sales_summary会失败,MySQL 不支持单视图粒度 - 如果视图里引用了
other_db.t1,用户还得有SELECT ON other_db.t1,否则展开定义时校验不过 - 若视图是
SQL SECURITY DEFINER且 DEFINER 用户已删,SHOW CREATE VIEW自身就失败,EXPLAIN必然卡住
如何只让运维看执行计划、不碰真实数据
核心思路是:用视图封装敏感基表,再只授 SHOW VIEW + SELECT on 视图本身,但不给基表 SELECT 权限。这样用户能 EXPLAIN v_safe_view,也能查视图结果,但查不到基表原始字段(比如用户密码、身份证号)。
但注意:仅靠视图不能完全隔离——如果用户有 SELECT on 基表,那视图形同虚设;所以必须确保基表权限未开放。
- 建视图时显式过滤敏感列,例如
CREATE VIEW v_user_summary AS SELECT id, name, dept FROM users(不包含password、phone) - 授权只给视图和对应库:
GRANT SHOW VIEW ON app_db.* TO 'ops'@'%'; GRANT SELECT ON app_db.v_user_summary TO 'ops'@'%' - 绝对不要授
SELECT ON app_db.users,否则绕过视图直查基表 - 若视图跨库(如 JOIN 了
log_db.access_log),需同步控制log_db的SELECT权限,否则EXPLAIN仍失败
EXPLAIN FORMAT=JSON 缺索引信息?补这两个 system 表权限
默认 EXPLAIN 能显示 type、key、rows 等基础字段,但 FORMAT=JSON 会尝试读取 information_schema.STATISTICS 和 information_schema.KEY_COLUMN_USAGE 来填充索引选择依据(比如 “为什么没走联合索引”)。没权限时 JSON 输出里 used_columns 或 possible_keys 可能为空或不完整。
- 补授权:
GRANT SELECT ON information_schema.STATISTICS TO 'ops'@'%'; GRANT SELECT ON information_schema.KEY_COLUMN_USAGE TO 'ops'@'%' - 不需要
SELECTon 其他information_schema表,这两个是FORMAT=JSON实际依赖的唯二表 - 权限生效无需
FLUSH PRIVILEGES,GRANT后立即可用
PROCESS 权限不是 EXPLAIN 必需,但调优时几乎必开
PROCESS 权限允许执行 SHOW PROCESSLIST,它不参与 EXPLAIN 计划生成,但在真实运维中极关键:当发现某条 EXPLAIN 出来的计划理论上很快,但实际卡住时,得靠 SHOW PROCESSLIST 看是否被锁等待、事务阻塞或 CPU 饱和。
- 授法:
GRANT PROCESS ON *.* TO 'ops'@'%' - 注意它是全局权限,不能限制到库或表;但风险可控,因它只暴露当前连接状态,不泄露数据内容
- 不加它,
EXPLAIN本身能跑,但你永远不知道“计划没问题,只是被别的事务堵死了”
真正容易被忽略的是:视图定义里隐含的跨库引用、DEFINER 用户状态、以及 information_schema 这两个表的权限缺失——它们不会让 EXPLAIN 直接报错,但会让输出信息残缺,误导判断。











