症状:,远程连接 mysql 很慢,但是 本地连接 mysql 很快, ping 和 route 网络通信都是正常的。

解决:mysql 的配置文件中增加如下配置参数:
[mysqld]
skip-name-resolve

原理:

作为MySQL调优的一部分,很多人都推荐开启skip_name_resolve。这个参数是禁止域名解析的(当然,也包括主机名)。很多童鞋会好奇,这背后的原理是什么,什么情况下开启这个参数比较合适。

基于以下原因,MySQL服务端会在内存中维护着一份host信息, 包括三部分:IP,主机名和错误信息。主要用于非本地TCP连接。

1. 通过在第一次建立连接时缓存IP和host name的映射关系,同一主机的后续连接将直接查看host cache,而不用再次进行DNS解析。

2. host cache中同样会包含IP登录失败的错误信息。可根据这些信息,对这些IP进行相应的限制。后面将会具体提到。

host cache的信息可通过performance_schema中host_cache表查看。

那么,IP和host name的映射关系是如何建立的呢?

1. 当有一个新的客户端连接进来时,MySQL Server会为这个IP在host cache中建立一个新的记录,包括IP,主机名和client lookup validation flag,分别对应host_cache表中的IP,HOST和HOST_VALIDATED这三列。第一次建立连接因为只有IP,没有主机名,所以HOST将设置为NULL,HOST_VALIDATED将设置为FALSE。

2. MySQL Server检测HOST_VALIDATED的值,如果为FALSE,它会试图进行DNS解析,如果解析成功,它将更新HOST的值为主机名,并将HOST_VALIDATED值设为TRUE。如果没有解析成功,判断失败的原因是永久的还是临时的,如果是永久的,则HOST的值依旧为NULL,且将HOST_VALIDATED的值设置为TRUE,后续连接不再进行解析,如果该原因是临时的,则HOST_VALIDATED依旧为FALSE,后续连接会再次进行DNS解析。

另,解析成功的标志并不只是通过IP,获取到主机名即可,这只是其中一步,还有一步是通过解析后的主机名来反向解析为IP,判断该IP是否与原IP相同,如果相同,才判断为解析成功,才能更新host cache中的信息。

基于上面的总结,下面谈谈 host cache的优缺点:

缺点:当有一个新的客户端连接进来时,MySQL Server都要建立一个新的记录,如果DNS解析很慢,无疑会影响性能。如果被允许访问的主机很多,也会影响性能,这个与host_cache_size有关,这个参数是5.6.5引入的。5.6.8之前默认是128,5.6.8之后默认是-1,基于max_connections的值动态调整。所以如果被允许访问的主机很多,基于LRU算法,先前建立的连接可能会被挤掉,这些主机重新进来时,会再次进行DNS查询。

优点:通常情况下,主机名是不变的,而IP是多变的。如果一个客户端的IP经常变化,那基于IP的授权将是一个繁琐的过程。因为你很难确定IP什么时候变化。而基于主机名,只需一次授权。而且,基于host cache中的失败信息,可在一定程度上阻止外界的暴力破解攻击。

关于阻止外界的暴力破解攻击,涉及到max_connect_errors参数,默认为100,官方的解释如下:

If more than this many successive connection requests from a host are interrupted without a successful connection, the server blocks that host from further connections.

如果某个客户端的连接达到了max_connect_errors的限制,将被禁止访问,并提示以下错误:

Host 'host_name' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

下面来模拟一下

首先,设置max_connect_errors的值

mysql> show variables like 'max_connect_errors';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| max_connect_errors | 100 |
+--------------------+-------+
1 row in set (0.00 sec) mysql> set global max_connect_errors=2;
Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'max_connect_errors';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| max_connect_errors | 2 |
+--------------------+-------+
1 row in set (0.00 sec)

通过telnet模拟interrupted without a successful connection。

[root@mysql-slave1 ~]# telnet 192.168.244.145 3306
Trying 192.168.244.145...
Connected to 192.168.244.145.
Escape character is '^]'.
N
5.6.26-log
K]qA1nYT!w|+ZhxF1c#|kmysql_native_password
^]
!#08S01Got packets out of orderConnection closed by foreign host.
[root@mysql-slave1 ~]# telnet 192.168.244.145 3306
Trying 192.168.244.145...
Connected to 192.168.244.145.
Escape character is '^]'.
N
Y#>PVB(>!Bl}NKnjIj]sMmysql_native_password
^]
!#08S01Got packets out of orderConnection closed by foreign host.
[root@mysql-slave1 ~]# mysql -h192.168.244.145 -uroot -p123456
Warning: Using a password on the command line interface can be insecure.
ERROR 1129 (HY000): Host '192.168.244.144' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

即便后来使用了正确的账号和密码登录,依旧会被阻止。

再来看看host_cache表中的信息,sum_connect_errors为2了。

mysql> select ip,host,host_validated,sum_connect_errors,count_authentication_errors from performance_schema.host_cache;
+-----------------+------+----------------+--------------------+-----------------------------+
| ip | host | host_validated | sum_connect_errors | count_authentication_errors |
+-----------------+------+----------------+--------------------+-----------------------------+
| 192.168.244.144 | NULL | YES | 2 | 0 |
+-----------------+------+----------------+--------------------+-----------------------------+
1 row in set (0.00 sec)

该阻止会一直生效,直到采取以下操作:

1. mysql> flush hosts;

2. # mysqladmin flush-hosts

3. truncate table performance_schema.host_cache;

4. 或者等待该记录从host cache中被挤掉。

如果要禁止DNS解析,可设置skip_name_resolve参数,这样,mysql.user表中基于主机名的授权将无法使用,且错误日志中会提示:

[Warning] 'user' entry 'root@mysql-slave1' ignored in --skip-name-resolve mode.

这里,通过mysql-slave1访问,将会拒绝访问

[root@mysql-slave1 ~]# mysql -h192.168.244.145 -uroot -p123
Warning: Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'192.168.244.144' (using password: YES)

host cache是默认开启的,如果要禁掉,可将host_cache_size设置为0,该参数是个动态参数,可在线修改。

如果要完全禁掉TCP/IP连接,可在MySQL启动时,设置skip-networking参数。

总结:

1. 从原理上看,DNS解析一般只针对客户端的第一次连接,客户端数据量比较小的情况下,开销其实不大,完全不必禁掉skip_name_resolve参数,带来的好处就是,为客户端和多变的IP直接解耦,只需对主机名进行一次授权。

可通过\s查看当前连接使用的是socket还是TCP。

2. 奇怪的是,对于skip_name_resolve参数,虽然官方文档说的是布尔值,

但如果在配置文件中指定了,无论是skip_name_resolve=off或者skip_name_resolve=0。

最后,通过show variables like '%skip_name_resolve%'查看均显示ON。将该参数设置为OFF的唯一办法是不写该参数(因为它默认值即为OFF)。

3. 在skip_name_resolve=ON的情况下,在本地通过-h127.0.0.1没有问题。

[root@localhost ~]# mysql -uroot -h127.0.0.1 -p123456
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.6.31-log MySQL Community Server (GPL) Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. root@(none) 09:02:15> \s
--------------
mysql Ver 14.14 Distrib 5.6.31, for Linux (x86_64) using EditLine wrapper Connection id: 4
Current database:
Current user: root@127.0.0.1
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.6.31-log MySQL Community Server (GPL)
Protocol version: 10
Connection: 127.0.0.1 via TCP/IP
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 11 min 10 sec Threads: 1 Questions: 20 Slow queries: 0 Opens: 70 Flush tables: 1 Open tables: 63 Queries per second avg: 0.029
-------------- root@(none) 09:02:18> show variables like '%skip_name_resolve%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| skip_name_resolve | ON |
+-------------------+-------+
1 row in set (0.06 sec)

如果该参数设置为OFF,则上述方式就会报错,通过报错信息可以看出,它直接将127.0.0.1转化为localhost了。

[root@localhost ~]# mysql -uroot -h127.0.0.1 -p123456 -P3306
Warning: Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

注意: 't1'@'%'中包含't1'@'127.0.0.1',如果开启skip_name_resolve参数,则't1'@'%'中定义的密码可用于't1'@'127.0.0.1'的登录,如果没有开启该参数,则't1'@'127.0.0.1'会转化为't1'@'localhost'登录,此时't1'@'%'定义的密码并不适用。

参考:http://www.cnblogs.com/ivictor/p/5311607.html

mysql之 远程连接 mysql 很慢,本地连接 mysql 很快 (skip-name-resolve)的更多相关文章

  1. 希赛网 > 问答 > 数据库 > MySQL数据库 > MySQL的管理与维护 > MySql开启远程用户登录GRANTALLPRIVILEGESON*.*TO'root'@'%'I MySql开启远程用户登录GRANTALLPRIVILEGESON*.*TO'root'@'%'I

    MySql开启远程用户登录 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'huawei' WITH GRANT OPTION; FL ...

  2. MySql开启远程用户登录GRANTALLPRIVILEGESON*.*TO'root'@'%'I MySql开启远程用户登录GRANTALLPRIVILEGESON*.*TO'root'@'%'I

    MySql开启远程用户登录 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'huawei' WITH GRANT OPTION; FL ...

  3. Mysql四种通信协议(linux下本地连接的都是socket 其他都是tcp)

    Mysql通信协议 - 张冲andy - 博客园 https://www.cnblogs.com/andy6/p/6204579.html

  4. 远程服务器的SqlServer允许本地连接

    最近做项目都是直接在阿里云买的服务器,并且SqlServer也是安装好的.但是默认的时候,这个服务器上的SqlServer并不允许直接在本地的SqlServer客户端访问,尽管服务器有公网IP. 想要 ...

  5. MySQL无法远程连接解决方案

    1.查看/etc/mysql/my.cnf配置文件是否只允许本地连接 注释配置:#bind-address = 127.0.0.1,重启MySQL Server 2.防火墙(我用的是iptables) ...

  6. 配置MySQL接受远程登录连接

    一 开放mysql mysql的配置文件在/etc/mysql/my.cnf文件内,里面有一行bind-address = 127.0.0.1表示只允许本地访问,将这行注释即可 # bind-addr ...

  7. bat脚本禁用和开启本地连接

    netsh interface set interface name="本地连接" admin=disabled //禁用本地连接 netsh interface set inte ...

  8. mysql开启远程连接及本地连接

    问题描述 在本机windows上连接linux服务器上的mysql报错:host'XXX' is not allowed to connect to this mysql server. 这个错误是由 ...

  9. 开启本地MySql数据库远程连接

    解决MySQL不允许从远程访问的方法 开启 MySQL 的远程登陆帐号有两大步: 1.确定服务器上的防火墙没有阻止 3306 端口. MySQL 默认的端口是 3306 ,需要确定防火墙没有阻止 33 ...

随机推荐

  1. zzuli1427 NO.6校赛----数字转换

    1427: 数字转换 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 572  Solved: 153 SubmitStatusWeb Board Des ...

  2. 从客户端(......)中检测到有潜在危险的 Request.Form 值

    在提交表单时候,asp.net 提示:"从客户端(......)中检测到有潜在危险的 Request.Form 值" .asp.net中的请求验证特性提供了某一等级的保护措施防止X ...

  3. PHP:第一章——PHP中常量和预定义常量

    <?php /*****************************************************/ //1.常量的定义 //常量:声明一次后长期不变的量,以字母或下划线开 ...

  4. web 攻击靶机解题过程

    sql注入靶机攻击过程请参考 https://pentesterlab.com/exercises/from_sqli_to_shell/course http://www.sohu.com/a/12 ...

  5. poj1088 滑雪 解题报告

    滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 77423   Accepted: 28779 Description ...

  6. 最全的CSS浏览器兼容问题【FF与IE】

    1. Div居中问题 div设置 margin-left, margin-right 为 auto 时已经居中,IE 不行,IE需要设定body居中,首先在父级元素定义text-algin: cent ...

  7. bzoj1087

    题解: 状压dp 代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; ; int n,m,cnt[ ...

  8. 关于python课程的想法和建议。

    第一次听说python是在刚结束与世隔绝的高中生活之后,当时的网络上铺天遍地都是人工智能和机器学习,于是便知道了python这门编程语言.我是光电信息科学与工程专业的学生,这个专业的学生必须要懂计算机 ...

  9. git账号申请及创建基线

    1.填写注册信息 https://github.com/ 进入官网 填写用户名,邮箱,密码然后点击sign up for github 2.后面不记得了,然后就可以创建项目了 3.填写项目名称及描述, ...

  10. Dev GridView-Bind Detail Grid during runtime

    Here is a simple example. ASPX <%@ Page Language="C#" AutoEventWireup="true" ...