应先执行select user, host from mysql.user where user = '' or user = 'test',列出所有匿名用户(如''@'localhost')和test账号;再根据mysql版本选择drop user或delete+flush privileges方式删除,并检查mysql.db、mysql.proxies_priv等表及代理、角色、外部配置中的残留引用。

查清所有匿名用户和测试账号
先执行 SELECT User, Host FROM mysql.user WHERE User = '' OR User = 'test';,把空用户名和 test 用户全列出来。注意 User = '' 是严格匹配空字符串,不是 IS NULL;test 用户常带 @'localhost' 或 @'%',必须连同 Host 一起看。别只扫一眼就删——有些 test 账号可能是监控脚本在用,''@'localhost' 也可能是旧系统免密登录入口。
区分 MySQL 版本再决定删除方式
MySQL 8.0+ 必须用 DROP USER,且必须写全 ''@'localhost' 这种格式;5.7 及更早版本虽然也支持 DROP USER,但部分安装包遗留的匿名用户可能不识别空 User,导致报错 ERROR 1396 (HY000): Operation DROP USER failed。这时得切回 DELETE FROM mysql.user WHERE User = '' AND Host IN ('localhost', '127.0.0.1', '::1'); + FLUSH PRIVILEGES; 组合。但注意:这个 DELETE 不清理 mysql.db 或 mysql.proxies_priv,删完还得手动检查这些表是否还有残留记录。
删之前务必确认没被代理或角色绑定
匿名用户和 test 用户哪怕权限为 USAGE,也可能被其他账号代理登录。运行这两条语句排查:
SELECT * FROM mysql.proxies_priv WHERE CONCAT(User, '@', Host) IN (''@'localhost', 'test'@'localhost');SELECT FROM_USER, TO_USER FROM mysql.role_edges WHERE FROM_USER IN ('', 'test');
如果返回结果非空,说明删了会导致依赖它的账号静默失败,得先解除代理或角色绑定,再删。
删完还要检查外部硬编码引用
删掉 test 用户后,应用突然连不上?大概率是 JDBC URL、ProxySQL 的 mysql_users 表、或者主从复制的 SOURCE_USER 里还写着它。查复制配置:SELECT SOURCE_USER, SOURCE_HOST FROM performance_schema.replication_connection_configuration;(MySQL 8.0.22+)或 SHOW SLAVE STATUS\G(旧版)。ProxySQL 用户则查 SELECT username FROM mysql_users WHERE username IN ('', 'test');。这些地方不会随 DROP USER 自动失效,必须人工同步清理。
真正麻烦的不是删本身,而是那些藏在配置文件和中间件里的硬编码用户名——它们不报错,只在下次连接池重建或服务重启时才暴露出来。











