MySQL远程登录时卡在“Connecting to…”阶段,很大概率是服务端在执行反向DNS解析时出现阻塞。这并非网络连通性或密码错误的问题,而是服务端调用gethostbyaddr()函数超时所致。解决方案很明确:启用skip-name-resolve参数,但必须同步调整权限表,否则依然无法成功连接。

如何确认DNS反向解析导致连接缓慢?
无需猜测,以下几种低成本验证方法能快速定位问题:
- 临时关闭本机DNS服务:
sudo systemctl stop systemd-resolved,然后执行mysql -h 192.168.1.50 -u app -p;如果瞬间连接成功,基本可以锁定原因 - 改用IPv6回环地址测试:
mysql -h ::1 -u root -p;若IPv4连接卡顿而IPv6立即响应,说明IPv4反向解析存在阻塞 - 登录MySQL后执行
SELECT @@skip_name_resolve;,返回0表示未开启跳过解析 - 通过
SHOW PROCESSLIST;查看,若出现大量状态为Connecting的线程,且Host列显示IP地址(如10.0.2.15:52183)而非域名,这就是典型特征
如何正确启用skip-name-resolve?
该参数仅对服务端生效,且必须写在[mysqld]配置段下。如果写错位置或修改后不重启服务,操作将毫无意义:
- 编辑配置文件(Linux常见路径:
/etc/my.cnf、/etc/mysql/mysql.conf.d/mysqld.cnf;Windows通常位于安装目录下的my.ini) - 在
[mysqld]段下添加:skip-name-resolve = ON - 必须重启服务:
sudo systemctl restart mysql(使用reload不会生效) - 验证是否生效:
mysql -e "SHOW VARIABLES LIKE 'skip_name_resolve';"返回ON才算成功 - Ubuntu/Debian系统下可能被
!includedir /etc/mysql/conf.d/覆盖,建议先运行mysqld --verbose --help | grep "Default options"确认最终加载的配置文件路径
启用skip-name-resolve后为何反而无法连接?
因为跳过DNS解析后,mysql.user表中的Host字段只能按字面值匹配IP或%,所有基于域名的授权记录将全部失效:
- 典型报错:
Access denied for user 'app'@'192.168.1.100',但执行SELECT User, Host FROM mysql.user;却显示'app'@'web01.example.com' - 本地使用
localhost可以连接,换成127.0.0.1就被拒绝——这是权限粒度变化的重要信号 - 修复方法:
UPDATE mysql.user SET Host = '192.168.1.100' WHERE User = 'app' AND Host = 'web01.example.com'; FLUSH PRIVILEGES; - 批量检查问题账号:
SELECT User, Host FROM mysql.user WHERE Host NOT IN ('%', 'localhost', '127.0.0.1', '::1'); - 在Kubernetes等动态IP环境下需谨慎使用:Pod IP频繁变动,硬编码IP不可持续,需要评估是否真的适合关闭反向解析
最容易被忽略的操作要点是:修改配置后未重启服务、改错了配置文件位置、或者只修改了服务端却没有同步更新mysql.user表——这三个环节中任何一个缺失,都会导致问题看起来“修复了但实际并未解决”。
