必须用 drop user 删除用户,它自动清理所有权限表且无需 flush privileges;但不终止现有连接,需手动 kill;注意用户名@主机名唯一性、大小写及代理/角色残留问题。

必须用 DROP USER,别碰 mysql.user 表
直接 DELETE FROM mysql.user 是危险操作,它只删主表,mysql.db、mysql.tables_priv 等权限表里的记录全留着。MySQL 8.0+ 还有内存级权限缓存,删表后不 FLUSH PRIVILEGES 就连不上;即使 flush 了,也可能触发 ERROR 1396 (HY000): Operation CREATE USER failed for 'xxx'@'%' ——系统认为用户“还存在”,但查 mysql.user 又找不到。
用户名@主机名必须写全,漏一个就残留
MySQL 用户由 'username'@'host' 共同唯一标识。'alice'@'localhost' 和 'alice'@'%' 是两个账号,删错或漏删任意一个都会导致权限残留。操作前务必执行:
-
SELECT User, Host FROM mysql.user WHERE User = 'alice';查清所有匹配项 -
SHOW GRANTS FOR 'alice'@'localhost';和SHOW GRANTS FOR 'alice'@'%';分别确认权限范围 - 注意大小写:用户名区分大小写,主机名不区分;通配符如
'192.168.%'必须原样拼写
DROP USER 自动清理全部权限表,但不杀活连接
DROP USER 是 DDL 操作,MySQL 内部会同步清理 mysql.user、mysql.db、mysql.tables_priv、mysql.proxies_priv 等所有关联表,无需手动 FLUSH PRIVILEGES。但它不会中断已有连接——老连接仍维持旧权限直到断开。若需立即阻断:
- 查连接:
SELECT CONCAT('KILL ', id, ';') FROM information_schema.processlist WHERE user = 'alice'; - 复制并执行生成的
KILL语句,或逐个KILL 1234;(不是KILL CONNECTION) - 特别注意代理关系:
SELECT * FROM mysql.proxies_priv WHERE CONCAT(User, '@', Host) = 'alice@%';,否则删 target 后 proxy 登录会静默失败
MySQL 8.0+ 要防角色残留,5.7 要补 FLUSH
如果用户被赋予过角色(GRANT role1 TO 'alice'@'%'),MySQL 8.0.16+ 会自动解除绑定但不删角色本身;5.7 则完全不处理角色,留下孤儿角色。建议删用户前先:
SELECT FROM_USER, TO_USER FROM mysql.role_edges WHERE FROM_USER = 'alice';-
REVOKE role1 FROM 'alice'@'%';(再DROP USER) - MySQL 5.7 建议删完补一句
FLUSH PRIVILEGES;,部分旧补丁版本有缓存延迟 - 别忘了检查配置文件:JDBC URL、ProxySQL 的
mysql_users表、主从复制的SOURCE_USER,这些地方硬编码的用户名不会随DROP USER自动失效
真正麻烦的从来不是命令敲不对,而是删完才发现应用还在连、配置没改、角色继承权限没断干净——尤其是用 'app'@'%' 这种通配符账号时,实际连接可能是 'app'@'10.20.30.40',删通配符用户根本不影响已有连接,新连接却挂了,误判成“删成功了”。











