mysql could not be resolved: Name or service not known
问题:mysqlDNS反解:skip-name-resolve
错误日志有类似警告:
1.12011916:26:04[Warning]IPaddress'192.168.1.10'couldnotberesolved:Nameorservicenotknown
2.12011916:26:04[Warning]IPaddress'192.168.1.14'couldnotberesolved:Nameorservicenotknown
3.12011916:26:04[Warning]IPaddress'192.168.1.17'couldnotberesolved:Nameorservicenotknown
通过showprocesslist发现大量类似如下的连接:
1.|592|unauthenticateduser|192.168.1.10:35320|NULL|Connect||login|NULL|
2.|593|unauthenticateduser|192.168.1.14:35321|NULL|Connect||login|NULL|
3.|594|unauthenticateduser|192.168.1.17:35322|NULL|Connect||login|NULL|
skip-name-resolve参数的作用:不再进行反解析(ip不反解成域名),这样可以加快数据库的反应时间。
修改配置文件添加并需要重启:
[mysqld] skip-name-resolve
其实就是在[mysqld]下面一行加入skip-name-resolve重启mysql服务就可以了。
下面是更加详细的解释:
现象:
程序连接mysql时,mysql的error.log里面提示:
[Warning]IPaddress'10.0.0.220'couldnotberesolved:Nameorservicenotknown
原因:
Mysql数据库服务器没有配置/etc/hosts,也没有DNS服务,导致mysqld线程解析IP对应的主机名时,解析失败。
参考资料:
Mysql域名解析:
当一个新的客户端尝试跟mysqld创建连接时,mysqld产生一个新线程来处理这个请求。新线程会先检查请求建立连接的主机名是否在Mysql的主机名缓冲中,如果不在,线程会尝试去解析请求连接的主机名。
解析的逻辑如下:
a.Mysql线程通过gethostbyaddr()把获取的IP地址解析成主机名,然后通过gethostbyname()把获取的主机名解析成IP地址,保障主机名和IP地址对应关系的准确;
b.如果操作系统支持使用安全进程的gethostbyaddr_r()和gethostbyname_r()调用,Mysqld线程可以用它俩来优化主机名解析;
c.如果操作系统不支持安全线程调用,Mysqld进程先做一个互斥锁,然后调用gethostbyaddr()和gethostbyname()解析主机名。此时,在第一个进程释放掉主机名缓冲池的主机名之前,其它进程无法再次解析这个主机名;<-------MySQL手册里面在此处说的hostname,意思应该是指同一个IP地址和对应的第一个主机名关系。
在启动mysqld进程是,可以使用--skip-name-resolve参数禁用DNS的主机名解析功能,禁用该功能后,在MySQL授权表里面,你只能使用IP地址。
如果你所处环境的DNS非常慢或者有很多主机,你可以通过禁用DNS解析功能--skip-name-resolve或者提高HOST_CACHE_SIZE大小来提升数据库的响应效率。
禁用主机名缓冲的发方法:使用--skip-host-cache参数;刷新主机名缓冲区:执行flushhosts或者执行mysqladminflush-hosts;
禁用TCP/IP连接:使用--skip-networking参数。
实验:
#grep192.168.1.1/etc/hosts
192.168.1.1hostname_online
sql>grantusageon*.*toroot@'h_tt_%'identifiedby'root';
sql>flushhosts;
#mysql-h192.168.1.1-uroot-proot
ERROR1045(28000):Accessdeniedforuser'root'@'hostname_online'(usingpassword:YES)###IP解析为hostname_online,不是h_tt_%,访问被拒。
#grep192.168.1.1/etc/hosts
192.168.1.1hostname_online
192.168.1.1h_tt_1
#mysql-h192.168.1.1-uroot-proot
ERROR1045(28000):Accessdeniedforuser'root'@'hostname_online'(usingpassword:YES)####mysqld没有刷新主机池缓冲池中的IP和主机名信息,此时IP对应hostname_online
sql>flushhosts;
#mysql-h192.168.1.1-uroot-proot
ERROR1045(28000):Accessdeniedforuser'root'@'hostname_online'(usingpassword:YES)####mysqld解析了/etc/hosts里面同一个IP对应的第一个主机名关系时,就不再解析后面这个IP对应的主机名关系
#grep192.168.1.1/etc/hosts
192.168.1.1h_tt_1
192.168.1.1hostname_online
sql>flushhosts;
#mysql-h192.168.1.1-uroot-proot
sql>exit
【实验:】验证解析相同IP对应的第一个主机名关系后,就不再解析相同IP:
Sql>grantusageon*.*toroot@'h_tt_%'identifiedby‘root';
Sql>flushhosts;
#greph_tt/etc/hosts#greph_tt/etc/hosts
192.168.1.1hostname_online192.168.1.1h_tt_1
192.168.1.1h_tt_1192,168.1.2h_tt_1
访问mysql被拒绝;从两个IP都可以访问mysql.
【结论】
此实验验证了,上述mysql手册中对"HowMySQLUsesDNS"的解释。
即mysqld线程解析/etc/hosts是,是以IP作为唯一标识的,及时一个IP对应了多个主机名,但是mysqld线程只解析第一条对应关系,不论后面有几条这个IP对应的不同主机名的记录,Mysqld进程都不会去解析,都是无效的。
【适用环境:】
没有DNS服务器,主机非常非常多,或者不想维护/etc/hosts里面手动配置的IP和主机名对应列表时,可以在mysql授权时执行主机名为"%"或者禁用IP和主机名解析功能(--skip-name-resolve)。