刚建的只读账号连不上,是因为MySQL 8.0不再自动授予USAGE权限,而它是登录连接的必要通行证;未授权information_schema.TABLES会导致SHOW CREATE TABLE报错;残留旧权限(如INSERT)未显式REVOKE会造成写操作意外成功。

直接用 CREATE USER + GRANT SELECT 不够,漏掉 USAGE 会导致连都连不上,漏掉 information_schema 权限会让 SHOW CREATE TABLE 报错,不 REVOKE 写权限可能被旧权限绕过——这三处是巡检账号上线即崩的高频原因。
为什么刚建的只读账号连不上?缺 USAGE 权限
MySQL 8.0 不再自动给新用户附带 USAGE。它不是“空权限”,而是登录连接的通行证。没它,哪怕密码正确,也会报 ERROR 1045 (28000): Access denied。
-
GRANT SELECT ON mydb.* TO 'inspector'@'192.168.10.%'只授权查数据,不解决登录问题 - 必须显式补上:
GRANT USAGE ON *.* TO 'inspector'@'192.168.10.%' -
USAGE和SELECT可以分开执行,顺序无关,但二者缺一不可 - 别用
'%'当主机名,巡检账号应限定内网段,比如'192.168.10.%'或具体跳板机 IP
为什么能连上却看不到表结构?information_schema 没授权
巡检脚本或 DBA 手动执行 SHOW CREATE TABLE users 时,MySQL 内部会去查 information_schema.TABLES。只授业务库权限,这条命令必然失败,报 ERROR 1142 (42000): SELECT command denied。
- 只需最小化授权:
GRANT SELECT ON `information_schema`.`TABLES` TO 'inspector'@'192.168.10.%' - 如需字段详情(比如
SHOW COLUMNS),再加:GRANT SELECT ON `information_schema`.`COLUMNS` TO 'inspector'@'192.168.10.%' - 绝对不要写
GRANT SELECT ON information_schema.*——部分表(如PROCESSLIST)需要额外权限,且扩大攻击面 - MySQL 8.0+ 默认收紧
information_schema访问,这是安全增强,不是 bug
为什么 INSERT 居然成功了?残留权限没清干净
权限是叠加的。如果这个用户名之前存在过、或匹配了其他 host 规则(比如同时有 'inspector'@'%' 和 'inspector'@'192.168.10.%'),旧的 INSERT 权限仍生效。更危险的是 SUPER——拥有它的人可以临时关掉 read_only。
- 先查清现状:
SHOW GRANTS FOR 'inspector'@'192.168.10.%' - 显式回收所有写类权限:
REVOKE INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, INDEX, LOCK TABLES, TRUNCATE, EXECUTE ON mydb.* FROM 'inspector'@'192.168.10.%' - 重点检查
SUPER:SELECT Super_priv FROM mysql.user WHERE User = 'inspector' AND Host = '192.168.10.%',若为Y,立刻REVOKE SUPER ON *.* FROM 'inspector'@'192.168.10.%' - 执行
FLUSH PRIVILEGES—— MySQL 8.0 虽多数情况自动刷新,但权限表直改或跨实例同步后必须手动刷
巡检账号真正的难点不在“怎么赋权”,而在“怎么确保没多给”。每次创建后,务必用新连接验证:查表成功、SHOW CREATE TABLE 成功、INSERT 明确报 ERROR 1142、连 mysql 库失败。任何一步通不过,都不是配置完成,只是配置了一半。


















