MySQL服务默认维护一个内存中的主机缓存,其中包含有关客户端的信息:IP地址、主机名,计数信息。当然,这里不包括本地主机TCP连接,环回接口地址(例如127.0.0.1或::1)建立的TCP连接,或者使用Unix套接字文件sock、命名管道或共享内存建立的连接,它不使用缓存。
MySQL服务将主机缓存用于以下2个目的:
- 通过缓存IP到主机名称查找的结果,可以避免对每个客户端连接进行域名系统(DNS)查找。相反,对于给定的主机,它只需要对来自该主机的第一个连接执行查找。
- 缓存包含有关客户端连接过程中发生的错误的信息。有些错误被认为是“阻塞”。如果给定主机连续发生太多错误而没有成功连接,MySQL服务会阻止该主机的进一步连接。这里max_connect_errors参数起到作用
当主机缓存达到错误次数(max_connect_errors)之后,连接请求被中断而没有成功连接后,MySQL服务会阻止该主机进行进一步的连接。如果在前一个连接中断后,在少于max_connect_errors的尝试次数内成功建立了来自主机的连接,则主机的错误计数将清除为零。
这些信息保存在Performance Schema 的host_cache表公开主机缓存的内容,以便可以使用SELECT语句对其进行检查。
mysql> SELECT * FROM performance_schema.host_cache\G;
*************************** 1. row ***************************
IP: 114.84.88.43
HOST: NULL
HOST_VALIDATED: YES
SUM_CONNECT_ERRORS: 0
COUNT_HOST_BLOCKED_ERRORS: 0
COUNT_NAMEINFO_TRANSIENT_ERRORS: 0
COUNT_NAMEINFO_PERMANENT_ERRORS: 1
COUNT_FORMAT_ERRORS: 0
COUNT_ADDRINFO_TRANSIENT_ERRORS: 0
COUNT_ADDRINFO_PERMANENT_ERRORS: 0
COUNT_FCRDNS_ERRORS: 0
COUNT_HOST_ACL_ERRORS: 0
COUNT_NO_AUTH_PLUGIN_ERRORS: 0
COUNT_AUTH_PLUGIN_ERRORS: 0
COUNT_HANDSHAKE_ERRORS: 0
COUNT_PROXY_USER_ERRORS: 0
COUNT_PROXY_USER_ACL_ERRORS: 0
COUNT_AUTHENTICATION_ERRORS: 1
COUNT_SSL_ERRORS: 0
COUNT_MAX_USER_CONNECTIONS_ERRORS: 0
COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS: 0
COUNT_DEFAULT_DATABASE_ERRORS: 0
COUNT_INIT_CONNECT_ERRORS: 0
COUNT_LOCAL_ERRORS: 0
COUNT_UNKNOWN_ERRORS: 0
FIRST_SEEN: 2024-07-24 10:28:49
LAST_SEEN: 2024-07-24 10:30:41
FIRST_ERROR_SEEN: 2024-07-24 10:28:49
LAST_ERROR_SEEN: 2024-07-24 10:30:41
1 row in set (0.00 sec)
字段 | 说明 |
---|---|
IP | 连接到服务器的客户端的IP地址。 |
HOST | 该客户端IP的解析DNS主机名,如果名称未知,则为NULL。 |
HOST_VALIDATED | 客户端IP的IP到主机名到IP DNS解析是否成功执行。 |
SUM_CONNECT_ERRORS | 为“阻塞”的连接错误数(根据max_connect_errors系统变量进行评估)。 |
COUNT_HOST_BLOCKED_ERRORS | 被阻止的连接数。 |
COUNT_NAMEINFO_TRANSIENT_ERRORS | IP到主机名DNS解析期间的瞬态错误数。 |
COUNT_NAMEINFO_PERMANENT_ERRORS | IP到主机名DNS解析期间的永久错误数。 |
COUNT_FCRDNS_ERRORS | 主机名格式错误数。 |
COUNT_ADDRINFO_PERMANENT_ERRORS | 主机名到IP反向DNS解析期间的瞬态错误数。 |
COUNT_ADDRINFO_PERMANENT_ERRORS | 主机名到IP反向DNS解析期间的永久错误数。 |
COUNT_FCRDNS_ERRORS | 正向确认的反向DNS错误数。 |
COUNT_HOST_ACL_ERRORS | 使用ACL连接的错误数。 |
COUNT_NO_AUTH_PLUGIN_ERRORS | 由于请求不可用的身份验证插件而导致的错误数。 |
COUNT_AUTH_PLUGIN_ERRORS | 身份验证插件报告的错误数。 |
COUNT_HANDSHAKE_ERRORS | 握手错误次数。 |
COUNT_PROXY_USER_ERRORS | 代理用户错误数。 |
COUNT_PROXY_USER_ACL_ERRORS | 代理用户ACL错误数。 |
COUNT_AUTHENTICATION_ERRORS | 身份验证失败导致的错误数。 |
COUNT_SSL_ERRORS | SSL问题导致的错误数。 |
COUNT_MAX_USER_CONNECTIONS_ERRORS | 超出用户的连接配额所导致的错误数。 |
COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS | 超过每小时连接配额所导致的错误数。 |
COUNT_DEFAULT_DATABASE_ERRORS | 默认数据库相关的错误数。 |
COUNT_INIT_CONNECT_ERRORS | init_connect语句执行失败导致的错误数。 |
COUNT_LOCAL_ERRORS | 本地连接的错误数,与网络、身份验证或授权无关。 |
COUNT_UNKNOWN_ERRORS | 其他未知错误的数量。 |
FIRST_SEEN | 第一次连接尝试的时间戳。 |
LAST_SEEN | 最近一次连接尝试的时间戳。 |
FIRST_ERROR_SEEN | 第一次错误的时间戳。 |
LAST_ERROR_SEEN | 最新错误的时间戳。 |
如果碰到堵塞,需要解除阻止被阻止的主机,需要刷新主机缓存。如 命令行FLUSH HOSTS 或 TRUNCATE:
mysql> FLUSH HOSTS;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------------------------------------------+
| Level | Code | Message | +---------+------+--------------------------------------------------------------------------------+
| Warning | 1287 | 'FLUSH HOSTS' is deprecated and will be removed in a future release. Please use TRUNCATE TABLE performance_schema.host_cache instead |
+---------+------+--------------------------------------------------------------------------------+
1 row in set (0.00 sec)
#也是使用host_cache_size,不记录主机缓存信息
mysql>SET GLOBAL host_cache_size=0;
主机缓存参数
到MySQL8.0版本主机缓存,有两个参数。
1. host_cache_size
该参数控制缓存数量,以及Performance Schema host_cache表的记录大小。默认是-1。无限制。
[mysqld]
host_cache_size=10
SET GLOBAL host_cache_size=20;
将大小设置为0将禁用主机缓存。禁用缓存后,服务器每次连接客户端时都会执行DNS查找。
2.skip_name_resolve
该参数用于控制MySQL服务在连接时是否进行主机名解析。主机名解析是将主机名转换为IP地址的过程,它涉及到网络通信和DNS查询。如果此变量为OFF,将在检查客户端连接时解析主机名。如果它是ON,只使用IP号码。然而,在某些情况下,主机名解析可能会导致查询的延迟,性能,无法连接等问题。通过设置该参数为ON,可以告诉MySQL服务跳过主机名解析步骤,直接使用IP地址进行查询,从而避免上述问题。
主机缓存影响参数
验证1:密码错误
首先先把max_connect_errors设置5,之后使用密码错误连续登录6次,最后一次正确登录。
#设置登录错误次数:
mysql> set global max_connect_errors=5;
#查看cache表:
mysql> SELECT * FROM performance_schema.host_cache\G;
备注:输入正确的密码仍可登录,说明max_connect_errors设置的值与输入密码错误次数无关。
验证2:网络延迟
使用tc qdisc模拟网络丢包延。延迟设置15000ms。因为connect_timeout默认是10s,所以延迟要大于这个值。
正确输入连接MySQL服务信息,当网络延迟导致连接丢失时(网络异常,网络超时等因素出现,就会导致这个握手协议无法完成)SUM_CONNECT_ERRORS,COUNT_HANDSHAKE_ERRORS 加1。
#设置延迟15s:
shell> tc qdisc add dev eth0 root netem delay 15000ms
#删除延迟:
shell> tc qdisc del dev eth0 root
达到max_connect_errors=5次之后,提示信息如下:
备注:从上述验证中,可以看出max_connection_errors设置值与密码输入错误的次数无关。跟网络通讯握手协议失败有关系。
3.系统设置
在Linux操作系统下的/etc/resolv.conf是DNS客户机配置文件,用于设置DNS服务器的IP地址及DNS域名,还包含了主机的域名搜索顺序。
resolv.conf的关键字主要有四个,分别是:
nameserver #定义DNS服务器的IP地址。
domain #定义本地域名。
search #定义域名的搜索列表。
sortlist #对返回的域名进行排序。
shell# cat /etc/resolv.conf
# Generated by NetworkManager
domain example.com
search example.com mysql.com
nameserver 192.168.1.10
nameserver 192.168.1.20
如开启MySQL的DNS解析,那这个文件需要关注下。还有/etc/hosts文件强制配置ip地址和其对应主机名。
总结
在日常的MySQL使用中,普遍关闭MySQL的DNS解析,较少影响数据库的稳定性和可用性。。因为日常维护中难免不会有IP变更,域名变更等维护工作,导致DNS解析失败,(如DNS服务器故障、网络问题或配置错误)。