仅执行GRANT SELECT无法确保真正只读,必须先SHOW GRANTS查残留权限、REVOKE所有写类权限、禁用SUPER、补USAGE及information_schema授权,并用新连接验证SELECT成功而INSERT/FOR UPDATE等失败。

只靠 GRANT SELECT 不能保证真正只读,必须显式清理残留权限、禁用 SUPER、补 USAGE 并验证新连接行为。
CREATE USER + GRANT SELECT 是起点,不是终点
MySQL 权限是叠加的,不是覆盖的。只执行 GRANT SELECT ON `reporting_db`.* TO 'bi_reader'@'10.20.%',用户仍可能因历史授权残留(比如曾被授过 ALL PRIVILEGES)而拥有写能力。
- 必须先查清当前权限:
SHOW GRANTS FOR 'bi_reader'@'10.20.%',重点看输出里是否含INSERT、UPDATE、DROP、ALTER、LOCK TABLES、EXECUTE、GRANT OPTION或SUPER -
USAGE不可省:它赋予“登录权”,没有它,用户认证通过后立刻断连,报ERROR 1045 (28000) - 库名带短横或特殊字符时,必须用反引号包裹,如
`my-app-db`.*;写成'my-app-db'.*会语法错误
REVOKE 写类权限比 GRANT 更关键
仅 GRANT SELECT 不起作用,必须主动撤销所有已知写权限项——漏掉一个 TRUNCATE 或 CREATE TEMPORARY TABLES 就可能被利用。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 标准撤销语句(针对单库):
REVOKE INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, INDEX, LOCK TABLES, EXECUTE, TRUNCATE, CREATE TEMPORARY TABLES ON `reporting_db`.* FROM 'bi_reader'@'10.20.%' - 检查全局高危权限:
SELECT User, Host, Super_priv FROM mysql.user WHERE User = 'bi_reader';若结果为Y,必须补:REVOKE SUPER ON *.* FROM 'bi_reader'@'10.20.%' - 不要依赖“没给就不让干”:MySQL 5.7+ 默认不开放
information_schema,但SHOW CREATE TABLE等操作会失败,需额外加GRANT SELECT ON `information_schema`.`TABLES` TO 'bi_reader'@'10.20.%'
验证必须用新连接,且测边界操作
旧连接缓存权限快照,FLUSH PRIVILEGES 后不重连就测试,结果完全不可信。
- 新开终端执行:
mysql -u bi_reader -p -h your-mysql-host - 必测项:
-
SELECT COUNT(*) FROM reporting_db.users;→ 应成功 -
INSERT INTO reporting_db.users(name) VALUES('test');→ 必须报ERROR 1142 (42000) -
SELECT * FROM reporting_db.users LIMIT 1 FOR UPDATE;→ 必须失败(FOR UPDATE需要LOCK TABLES,你已 REVOKE) -
SHOW CREATE TABLE reporting_db.users;→ 若失败,说明缺information_schema授权
-
最容易被忽略的是 SUPER 权限和 USAGE 缺失——前者能让用户绕过只读限制直接改系统变量,后者会让账号根本连不上,现象像密码错,实则权限配置不全。

















