show grants或连接验证慢的本质是dns反向解析、权限表未走索引、数据量大或缓存失效;默认skip_name_resolve=off时,每个新连接都会尝试反解客户端ip,导致延迟;应设为on并重启,用真实ip测试,查询权限时必须带host条件且避免通配符开头,及时analyze table并用grant而非直接update。

为什么 SHOW GRANTS 或连接验证特别慢?
本质是 MySQL 在查权限时触发了 DNS 反向解析,或权限表(mysql.user、mysql.db 等)没走索引、数据量大、或缓存失效后反复刷盘。尤其在启用了 skip_name_resolve=OFF(默认)时,每个新连接都会尝试把客户端 IP 反解成 hostname,卡住几秒很常见。
- 检查是否真被 DNS 卡住:
tcpdump -i any port 53看是否有大量 DNS 查询; - 确认
skip_name_resolve是否已设为ON(需重启 mysqld 生效); - 别用
localhost测试——它走 socket,不触发 host 解析,会掩盖问题; - 用真实 IP 连接复现:
mysql -h 192.168.1.100 -u testuser -p。
权限表查询慢:mysql.user 没走主键?
MySQL 5.7+ 的 mysql.user 表主键是 (Host, User),但如果你用 SELECT * FROM mysql.user WHERE User='xxx',就只能全表扫描。更糟的是,如果手动改过 Host 字段(比如写成 '%.example.com'),会导致范围匹配变慢,且无法利用前缀索引优化。
- 查权限必须带
Host条件:SELECT * FROM mysql.user WHERE Host='192.168.1.%' AND User='app'; - 避免通配符开头:
'%myapp'无法用索引,'myapp%'可以; - 执行
ANALYZE TABLE mysql.user;更新统计信息(尤其批量导入用户后); - 别直接 UPDATE
mysql.user,用GRANT/CREATE USER,它们会自动刷新内存缓存。
FLUSH PRIVILEGES 之后还是慢?可能是权限缓存没清干净
MySQL 服务端会把权限缓存在线程级和全局级两层。仅执行 FLUSH PRIVILEGES 只刷新全局缓存,但已有连接的线程缓存仍沿用旧快照,直到该连接断开或显式重载。
- 新连接立即生效,老连接不会自动更新权限视图;
- 如果发现改完权限后某连接行为异常,直接
KILL对应线程(SHOW PROCESSLIST查ID); - 应用层注意连接池复用:即使服务端权限已更新,连接池里“活着”的旧连接仍按旧权限跑;
- 验证缓存状态可查
SELECT @@global.skip_name_resolve;和SELECT USER(), CURRENT_USER();——后者才是实际匹配的权限主体。
性能敏感场景下,如何绕过权限校验瓶颈?
不是所有环境都能关 DNS 解析或动权限表结构。当业务对连接建立延迟极度敏感(如短连接高频调用),可以考虑降级方案,但得清楚代价。
- 强制走 Unix socket 连接(仅限本机):
mysql -S /var/run/mysqld/mysqld.sock -u user,跳过 TCP 层和 Host 解析; - 用
localhost时确保配置文件里没混用127.0.0.1——前者走 socket,后者走 TCP; - 禁用
check_proxy_users插件(如果没用代理认证); - 极端情况可临时关闭
validate_password插件(它会在每次登录时校验密码强度,增加开销)。
真正卡点往往不在 SQL 权限逻辑本身,而在网络层解析、缓存粒度、以及连接复用方式。改一个配置、换一种连接写法,比优化 SQL 更快见效。











