MySQL 服务器维护一个内存中的主机缓存,其中包含有关客户端的信息:IP 地址、主机名和错误信息。性能模式 host_cache
表公开主机缓存的内容,以便可以使用 SELECT
语句对其进行检查。这可能有助于您诊断连接问题的根源。请参阅 第 29.12.22.3 节,“host_cache 表”.
以下部分将讨论主机缓存的工作原理,以及其他主题,例如如何配置和监控缓存。
服务器仅对非本地主机 TCP 连接使用主机缓存。它不使用缓存来建立使用回环接口地址(例如,127.0.0.1
或 ::1
)的 TCP 连接,也不使用缓存来建立使用 Unix 套接字文件、命名管道或共享内存的连接。
服务器将主机缓存用于以下几种用途
通过缓存 IP 到主机名查找的结果,服务器避免对每个客户端连接执行域名系统 (DNS) 查找。相反,对于给定的主机,它只需要对来自该主机的第一个连接执行查找。
缓存包含有关客户端连接过程中发生的错误的信息。某些错误被认为是 “阻止” 的。如果来自给定主机的这些错误连续发生太多次,而没有成功连接,则服务器会阻止来自该主机的进一步连接。
max_connect_errors
系统变量确定在阻止发生之前允许的连续错误次数。
对于每个适用的新的客户端连接,服务器使用客户端 IP 地址检查客户端主机名是否在主机缓存中。如果在,则服务器拒绝或继续处理连接请求,具体取决于主机是否被阻止。如果主机不在缓存中,则服务器尝试解析主机名。首先,它将 IP 地址解析为主机名,并将该主机名解析回 IP 地址。然后,它将结果与原始 IP 地址进行比较,以确保它们相同。服务器将此操作的结果信息存储在主机缓存中。如果缓存已满,则会丢弃最少最近使用过的条目。
服务器使用 getaddrinfo()
系统调用执行主机名解析。
服务器处理主机缓存中的条目如下
当第一个 TCP 客户端连接从给定的 IP 地址到达服务器时,会创建一个新的缓存条目来记录客户端 IP、主机名和客户端查找验证标志。最初,主机名设置为
NULL
,标志为 false。此条目也用于来自相同源 IP 的后续客户端 TCP 连接。如果客户端 IP 条目的验证标志为 false,则服务器尝试执行 IP 到主机名到 IP 的 DNS 解析。如果成功,则主机名将使用解析的主机名进行更新,并将验证标志设置为 true。如果解析不成功,则采取的措施取决于错误是永久性的还是暂时的。对于永久性失败,主机名保持
NULL
,并将验证标志设置为 true。对于临时失败,主机名和验证标志保持不变。(在这种情况下,下次客户端从该 IP 连接时,将执行另一次 DNS 解析尝试。)如果在处理来自给定 IP 地址的传入客户端连接时发生错误,则服务器会更新该 IP 条目中的相应错误计数器。有关记录的错误的描述,请参阅 第 29.12.22.3 节,“host_cache 表”.
要解除被阻止的主机的阻止,请刷新主机缓存;请参阅 处理被阻止的主机.
即使没有刷新主机缓存,被阻止的主机也可能由于其他主机的活动而解除阻止
如果缓存已满,而来自不在缓存中的客户端 IP 的连接到达,则服务器会丢弃最少最近使用过的缓存条目,为新条目腾出空间。
如果丢弃的条目是针对被阻止的主机,则该主机将解除阻止。
某些连接错误与 TCP 连接无关,在连接过程的早期(甚至在 IP 地址已知之前)发生,或者不特定于任何特定 IP 地址(例如内存不足情况)。有关这些错误的信息,请查看 Connection_errors_
状态变量(参见 第 7.1.10 节,“服务器状态变量”)。xxx
主机缓存默认启用。 host_cache_size
系统变量控制其大小,以及 Performance Schema host_cache
表的大小,该表公开缓存内容。缓存大小可以在服务器启动时设置,并在运行时更改。例如,要在启动时将大小设置为 100,请在服务器 my.cnf
文件中添加以下行
[mysqld]
host_cache_size=200
要在运行时将大小更改为 300,请执行以下操作
SET GLOBAL host_cache_size=300;
在服务器启动时或运行时将 host_cache_size
设置为 0 将禁用主机缓存。禁用缓存后,服务器将在每次客户端连接时执行 DNS 查找。
在运行时更改缓存大小会导致隐式主机缓存刷新操作,该操作将清除主机缓存,截断 host_cache
表,并取消阻止任何被阻止的主机;参见 刷新主机缓存.
要禁用 DNS 主机名查找,请在启用 skip_name_resolve
系统变量的情况下启动服务器。在这种情况下,服务器仅使用 IP 地址,而不是主机名,将连接主机与 MySQL 授权表中的行匹配。只有在这些表中使用 IP 地址指定的帐户才能使用。(如果不存在指定客户端 IP 地址的帐户,客户端可能无法连接。)
如果您有一个非常慢的 DNS 和许多主机,您可能可以通过启用 skip_name_resolve
来禁用 DNS 查找,或者通过增加 host_cache_size
的值来使主机缓存更大,从而提高性能。
要完全禁止 TCP/IP 连接,请在启用 skip_networking
系统变量的情况下启动服务器。
要调整在主机被阻止之前允许的连续连接错误次数,请设置 max_connect_errors
系统变量。例如,要在启动时设置该值,请在服务器 my.cnf
文件中添加以下行
[mysqld]
max_connect_errors=10000
要在运行时更改该值,请执行以下操作
SET GLOBAL max_connect_errors=10000;
Performance Schema host_cache
表公开主机缓存的内容。可以使用 SELECT
语句检查此表,这可能有助于诊断连接问题的根源。有关此表的信息,参见 第 29.12.22.3 节,“host_cache 表”.
在以下情况下,可能建议或需要刷新主机缓存
您的某些客户端主机更改了 IP 地址。
来自合法主机的连接出现错误消息
Host '
。(参见 处理被阻止的主机。)host_name
' is blocked
刷新主机缓存具有以下效果
它会清除内存中的主机缓存。
它会从 Performance Schema
host_cache
表中删除所有行,该表公开缓存内容。它会取消阻止任何被阻止的主机。这将允许来自这些主机的进一步连接尝试。
要刷新主机缓存,可以使用以下任何方法
更改
host_cache_size
系统变量的值。这需要SYSTEM_VARIABLES_ADMIN
权限(或已弃用的SUPER
权限)。执行
TRUNCATE TABLE
语句,该语句会截断 Performance Schemahost_cache
表。这需要该表的DROP
权限。执行 mysqladmin flush-hosts 命令。这需要 Performance Schema
host_cache
表的DROP
权限或RELOAD
权限。
服务器使用主机缓存来跟踪客户端连接过程中发生的错误。如果出现以下错误,则表示 mysqld 收到了来自给定主机的许多连接请求,这些请求在中途被中断
Host 'host_name' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'
max_connect_errors
系统变量的值决定了服务器在阻止主机之前允许多少个连续的中断连接请求。在 max_connect_errors
次失败请求(没有成功连接)之后,服务器会假设出了问题(例如,有人试图侵入),并阻止该主机进行进一步的连接请求。
要取消阻止被阻止的主机,请刷新主机缓存;参见 刷新主机缓存.
或者,要避免出现错误消息,请按照 配置主机缓存 中的说明设置 max_connect_errors
。 max_connect_errors
的默认值为 100。将 max_connect_errors
增加到一个较大的值,可以降低主机达到阈值并被阻止的可能性。但是,如果出现错误消息 Host '
,请首先验证来自被阻止主机的 TCP/IP 连接是否正常。如果存在网络问题,增加 host_name
' is blockedmax_connect_errors
的值毫无意义。