REVOKE INSERT, UPDATE, DELETE, CREATE, DROP, ALTER ON . 不能真正回收全局写权限,因其仅撤销显式语句级权限,而用户仍可通过角色、mysql.user 表布尔字段(如 Create_priv)、空用户(''@'')及 mysql.db 库级权限隐式执行写操作,需逐层清理并终止旧连接。

直接执行 REVOKE INSERT, UPDATE, DELETE, CREATE, DROP, ALTER ON *.* FROM 'user'@'host'; 不能真正回收全局写权限——它只撤显式授予的语句级权限,而用户可能通过角色、mysql.user 表字段或空用户隐式权限继续执行写操作。
为什么 REVOKE ... ON *.* 不够用
MySQL 的“全局写权限”不是单一权限项,而是由多层机制共同支撑:显式 GRANT、角色绑定、mysql.user 中的管理字段(如 Create_priv)、以及空用户(''@'')对 information_schema 等系统库的默认 SELECT(虽不直接写,但影响元数据操作)。仅靠 REVOKE 语句只能清理第一层。
-
REVOKE INSERT ON *.*对CREATE、DROP等权限无效,必须逐个列出或用ALL PRIVILEGES - 若用户绑定了
db_admin角色,解绑前REVOKE显式权限毫无意义 -
mysql.user表中Create_priv、Drop_priv、Alter_priv字段为'Y'时,即使没显式GRANT,该用户仍能建库删表
必须清理 mysql.user 表中的布尔权限字段
这些字段是独立于 GRANT/REVOKE 流程的硬编码开关,只靠 SQL 权限语句无法触达。例如 Create_priv 控制 CREATE DATABASE,Drop_priv 控制 DROP DATABASE,它们在 SHOW GRANTS 中完全不显示。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 先查当前状态:
SELECT Host, User, Create_priv, Drop_priv, Alter_priv, Insert_priv, Update_priv, Delete_priv FROM mysql.user WHERE User = 'u1' AND Host = '%'; - 逐项设为
'N':UPDATE mysql.user SET Create_priv = 'N', Drop_priv = 'N', Alter_priv = 'N', Insert_priv = 'N', Update_priv = 'N', Delete_priv = 'N' WHERE User = 'u1' AND Host = '%'; - 必须执行
FLUSH PRIVILEGES;—— 这次不是可选项,因为绕过了权限缓存更新机制
别漏掉角色和空用户带来的隐式写能力
角色可能包含 CREATE TABLE 或 DROP INDEX 等细粒度权限;空用户(''@'')虽不能写业务库,但能读写 performance_schema 和 sys,某些场景下可间接触发写行为(如调用存储过程修改状态表)。
- 查是否绑角色:
SELECT FROM_HOST, FROM_USER, TO_HOST, TO_USER FROM mysql.role_edges WHERE TO_USER = 'u1' AND TO_HOST = '%'; - 解绑所有角色:
REVOKE 'role1', 'role2' FROM 'u1'@'%';(注意主机名必须完全一致) - 查空用户授权:
SELECT Host, Db, Create_priv, Drop_priv FROM mysql.db WHERE User = '' AND Host = '' AND (Create_priv = 'Y' OR Drop_priv = 'Y'); - 如有匹配,回收:
REVOKE CREATE, DROP ON *.* FROM ''@'';
活跃连接会缓存旧权限,必须主动终止
所有上述操作只对新连接生效。已建立的连接(包括应用连接池里的长连接)仍以旧权限运行,INSERT INTO mysql.user 或 DROP TABLE 可能继续成功。
- 定位目标连接:
SELECT ID, USER, HOST, COMMAND, TIME FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'u1'; - 逐个终止:
KILL CONNECTION [ID];(推荐用带CONNECTION的语法,更明确) - 通知应用重启连接池,或等待其超时重连;不要依赖
FLUSH PRIVILEGES让旧连接“自动同步”
最易被忽略的是:即使你清空了所有显式权限、更新了 mysql.user、解绑了角色,只要没查 mysql.db 里空用户的 Create_priv,用户仍可能通过 CREATE DATABASE IF NOT EXISTS test 创建测试库——因为这条语句不检查 *.* 级权限,而走 mysql.db 的库级判断逻辑。

















