本文问题
- 主机缓存的内容和作用是什么?
- 主机缓存是如何进行更新的?
- 如何设置主机缓存是否启用及主机缓存的大小?
- 主机缓存中的错误消息有什么作用?
- 如何清空主机缓存?
- 如何查看已缓存的主机信息?
主机缓存
MySQL服务器在内存中维护关于客户端的主机缓存,内容包括:IP地址、主机名和错误信息。
主机缓存作用
- 通过缓存IP到主机名的对应关系,服务器可以避免对每个客户端连接进行DNS解析。对于给定的主机,只需要对第一个连接进行解析即可。
- 缓存中包含了在连接过程中发生的错误信息。一些错误被认为是‘阻塞’。如果一个主机连续发生了太多‘阻塞',数据库会拒绝这个主机的连接
对于每个新的客户端连接,服务器使用IP地址来检查客户端的主机名是否在主机缓存中。如果在主机缓存中,数据库根据缓存中的内容来决定是否接受连接。如果不在主机缓存中,数据库会尝试解析主机名:首先,将IP地址解析为主机名并将主机名反向解析为IP地址。然后,服务器将解析后的IP地址和原始IP地址比较,确定两个IP地址相同。数据库将结果记录在主机缓存中。如果缓存已满,则丢弃最近最少使用的记录。
主机缓存的更新
- 当一个客户端从指定的IP地址第一次连接到服务器时,创建一个新的缓存记录,记录包括客户端IP地址,主机名和客户端解析验证标记。最初,主机名设置为
NULL
,标识设置为false
。这个记录用于同一IP地址之后的其他客户端连接 - 如果条目的验证标识为
false
,服务器尝试进行IP到主机名 主机名到IP的DNS解析。如果解析程工。主机名更新为解析到的主机名并且验证标记更新为true
。如果解析失败,则采取的措施取决于错误是暂时错误还是永久的错误。对于永久的错误,主机名保持NULL
不变,验证标识更新为true
。对于暂时的错误,主机名和验证标识都保持不变,当下一次相同IP的客户端连接时,还会再次尝试DNS解析。 - 如果在处理客户端连接的时候发生了错误,服务器会更新对应IP地址的相关错误计数器。
数据库使用gethostbyaddr()
和gethostbyname()
系统调用进行主机名解析
清空Host缓存
如果一个主机连续发生了太多‘阻塞’的错误,数据库会拒绝这个主机继续连接到数据库(锁定主机)。再进行连接时,会提示以下错误:
Host 'host_name' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'
max_connect_errors
决定了最大错误次数。默认值是100。
手动解锁主机的唯一方法是刷新主机缓存
mysql> FLUSH HOSTS
mysql>TRUNCATE TABLE performance_schema.host_cache
shell> mysqladmin flush-hosts
由于主机缓存具有最大大小,当其他主机连接数据库后,如果缓存超过了最大缓存大小,并且被锁定的主机恰好是最近最少使用的主机,也有可能会将这个主机从主机缓存中清楚,主机会自动解锁。
查看Host缓存信息
可以通过Performance_Schema.host_cache
表来查看主机缓存信息
host_cache
表结构
mysql> desc performance_schema.host_cache;
+--------------------------------------------+------------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------------------------+------------------+------+-----+---------------------+-------+
| IP | varchar(64) | NO | | NULL | |
| HOST | varchar(255) | YES | | NULL | |
| HOST_VALIDATED | enum('YES','NO') | NO | | NULL | |
| SUM_CONNECT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_HOST_BLOCKED_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_NAMEINFO_TRANSIENT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_NAMEINFO_PERMANENT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_FORMAT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_ADDRINFO_TRANSIENT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_ADDRINFO_PERMANENT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_FCRDNS_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_HOST_ACL_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_NO_AUTH_PLUGIN_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_AUTH_PLUGIN_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_HANDSHAKE_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_PROXY_USER_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_PROXY_USER_ACL_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_AUTHENTICATION_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_SSL_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_MAX_USER_CONNECTIONS_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_DEFAULT_DATABASE_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_INIT_CONNECT_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_LOCAL_ERRORS | bigint(20) | NO | | NULL | |
| COUNT_UNKNOWN_ERRORS | bigint(20) | NO | | NULL | |
| FIRST_SEEN | timestamp | NO | | 0000-00-00 00:00:00 | |
| LAST_SEEN | timestamp | NO | | 0000-00-00 00:00:00 | |
| FIRST_ERROR_SEEN | timestamp | YES | | 0000-00-00 00:00:00 | |
| LAST_ERROR_SEEN | timestamp | YES | | 0000-00-00 00:00:00 | |
+--------------------------------------------+------------------+------+-----+---------------------+-------+
配置Host缓存
默认情况下,启用主机缓存。
设置缓存大小
缓存大小可以动态修改,修改缓存大小会清除缓存。
[mysqld]
host_cache_size=200
SET GLOBAL host_cache_size=300;
禁用主机缓存
在禁用主机缓存的情况下,每次客户端连接的时候都要进行DNS解析
--skip-host-cache
只能在数据库启动时设置,优先级更高。
host_cache_size=0
可以在数据库运行时修改。
禁用DNS解析
启用skip_name_resolve
可以禁止DNS解析,在这种情况下,数据库只检查IP地址是否与权限表中的记录匹配。
问题答案
- 主机缓存的内容和作用是什么?
- 内容
主机缓存中包括IP地址、主机名和一些错误信息 - 作用:
- 通过缓存主机,同一主机可以只在第一次连接时进行DNS解析,避免对每个连接都进行DNS解析。
- 主机缓存中会记录连接错误,同一主机连续多次出现阻塞性错误(超过max_connect_errors)可以拒绝该主机继续连接
- 主机缓存是如何进行更新的?
- 添加
- 当一个主机第一次连接时,创建一个新的缓存条目来记录主机信息(
IP地址,主机名=NULL,验证标识=false
)。 - 如果
验证标识=false
,尝试用IP地址解析主机名。- 解析成功
主机名=hostname,验证标识=true
- 解析失败
- 暂时性错误
主机名=NULL,验证标识=false
。相同主机下次连接时还会进行DNS解析 - 永久性错误
主机名=NULL,验证标识=true
- 暂时性错误
- 解析成功
- 当一个主机第一次连接时,创建一个新的缓存条目来记录主机信息(
- 更新
在处理客户端连接时发生错误,会更新主机缓存中对应IP地址相关的错误计数器。 - 删除
当缓存已满时,按照最近最少使用(LRU)算法驱逐缓存中的记录
- 如何设置主机缓存是否启用及主机缓存的大小?
主机缓存默认启用,可以通过--skip-host-cache
禁用。
可以通过host_cache_size
来修改主机缓存的大小,大小为0
时禁用主机缓存。每次修改主机缓存的大小都会清空主机缓存。
在使用--skip-host-cache
禁用主机缓存后,修改host_cache_size
的大小不会启用主机缓存。 - 主机缓存中的错误消息有什么作用?
一些错误是阻塞性的,当一个主机连续发生的阻塞性错误数量超过max_connect_errors
的值时,数据库会拒绝这个主机继续连接。可以通过清空主机缓存来允许主机继续连接 - 如何清空主机缓存?
shell> mysqladmin flush-hosts
flush hosts
truncate table performance_schema.host_cache
set global host_cache_size=n
- 如何查看已缓存的主机信息?
查询performance_schema.host_cache
表
网友评论