#### 5.1.12.3 DNS查找和主机缓存

[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)

MySQL服务器维护内存中的主机缓存，其中包含有关客户端的信息：IP地址、主机名和错误信息。性能模式[`主机缓存`](performance-schema-host-cache-table.html)表公开主机缓存的内容，以便使用[`选择`](select.html)声明。这可能有助于诊断连接问题的原因。看见[第27.12.21.2节，“主机\_“缓存表”](performance-schema-host-cache-table.html).

以下各节讨论主机缓存的工作方式，以及其他主题，如如何配置和监视缓存。

-   [主机缓存操作](host-cache.html#host-cache-operation)

-   [配置主机缓存](host-cache.html#host-cache-configuration)

-   [监视主机缓存](host-cache.html#host-cache-monitoring)

-   [刷新主机缓存](host-cache.html#host-cache-flushing)

-   [处理被阻止的主机](host-cache.html#blocked-host)

##### 主机缓存操作

服务器仅将主机缓存用于非本地主机TCP连接。它不会将缓存用于使用环回接口地址建立的TCP连接（例如，`127.0.0.1`或`::1`)，或用于使用Unix套接字文件、命名管道或共享内存建立的连接。

服务器将主机缓存用于多种用途：

-   通过缓存IP到主机名查找的结果，服务器可以避免对每个客户端连接进行域名系统（DNS）查找。相反，对于给定的主机，它只需要对来自该主机的第一个连接执行查找。

-   缓存包含有关客户端连接过程中发生的错误的信息。有些错误被认为是“阻塞”如果在没有成功连接的情况下，在给定主机上连续出现过多这样的情况，服务器会阻止来自该主机的进一步连接。这个[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)系统变量确定阻塞发生前允许的连续错误数。

    对于每个适用的新客户端连接，服务器使用客户端 IP 地址检查客户端主机名是否在主机缓存中。如果是，则服务器根据主机是否被阻塞，拒绝或继续处理连接请求。如果主机不在缓存中，服务器会尝试解析主机名。首先，它将 IP 地址解析为主机名，然后将该主机名解析回 IP 地址。然后它将结果与原始 IP 地址进行比较，以确保它们相同。服务器将有关此操作结果的信息存储在主机缓存中。如果缓存已满，则丢弃最近最少使用的条目。

    服务器使用`gethostbyaddr()`和`获取主机名（）`系统调用。

    服务器处理主机缓存中的条目，如下所示：

1.  当第一个 TCP 客户端连接从给定的 IP 地址到达服务器时，会创建一个新的缓存条目来记录客户端 IP、主机名和客户端查找验证标志。最初，主机名设置为`空值`并且标志是假的。此条目还用于来自同一原始 IP 的后续客户端 TCP 连接。

2.  如果客户端 IP 条目的验证标志为假，则服务器尝试 IP 到主机名到 IP DNS 解析。如果成功，则使用解析的主机名更新主机名，并将验证标志设置为 true。如果解决不成功，则采取的措施取决于错误是永久性的还是暂时性的。对于永久性故障，主机名保持不变`空值`并且验证标志设置为真。对于暂时性故障，主机名和验证标志保持不变。（在这种情况下，下次客户端从该 IP 连接时会发生另一次 DNS 解析尝试。）

3.  如果在处理来自给定 IP 地址的传入客户端连接时发生错误，则服务器会更新该 IP 条目中的相应错误计数器。有关记录的错误的说明，请参阅[第 27.12.21.2 节，“主机\_缓存表”](performance-schema-host-cache-table.html).

    要解除阻塞的主机，请刷新主机缓存；看[处理被阻止的主机](host-cache.html#blocked-host).

    如果发生来自其他主机的活动，即使没有刷新主机缓存，被阻止的主机也可能会变得畅通：

-   如果当连接从不在缓存中的客户端 IP 到达时缓存已满，则服务器丢弃最近最少使用的缓存条目以为新条目腾出空间。

-   如果丢弃的条目是针对被阻止的主机的，则该主机将被解除阻止。

    一些连接错误与 TCP 连接无关，发生在连接过程的早期（甚至在知道 IP 地址之前），或者不是特定于任何特定 IP 地址的（例如内存不足的情况）。有关这些错误的信息，请查看[`连接错误_*`xxx`*`](server-status-variables.html#statvar_Connection_errors_xxx)状态变量（见[第 5.1.10 节，“服务器状态变量”](server-status-variables.html)）。

##### 配置主机缓存

默认情况下启用主机缓存。这[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)系统变量控制它的大小，以及 Performance Schema 的大小[`主机缓存`](performance-schema-host-cache-table.html)公开缓存内容的表。缓存大小可以在服务器启动时设置并在运行时更改。例如，要在启动时将大小设置为 100，请将这些行放在服务器中`我的.cnf`文件：

```
[mysqld]
host_cache_size=200
```

要在运行时将大小更改为 300，请执行以下操作：

```
SET GLOBAL host_cache_size=300;
```

环境`主机缓存大小`为 0，无论是在服务器启动时还是在运行时，都会禁用主机缓存。禁用缓存后，每次客户端连接时，服务器都会执行 DNS 查找。

在运行时更改缓存大小会导致隐式主机缓存刷新操作，该操作会清除主机缓存，截断[`主机缓存`](performance-schema-host-cache-table.html)表，并取消阻止任何被阻止的主机；看[刷新主机缓存](host-cache.html#host-cache-flushing).

使用[`--skip-host-cache`](server-options.html#option_mysqld_skip-host-cache)选项类似于设置[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)系统变量为 0，但[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)更灵活，因为它还可以用于在运行时调整、启用和禁用主机缓存，而不仅仅是在服务器启动时。启动服务器[`--skip-host-cache`](server-options.html#option_mysqld_skip-host-cache)不会阻止运行时更改[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)，但是这样的更改没有效果，并且缓存不会重新启用，即使[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)设置为大于 0。

要禁用 DNS 主机名查找，请使用[`跳过名称解析`](server-system-variables.html#sysvar_skip_name_resolve)系统变量启用。在这种情况下，服务器只使用 IP 地址而不是主机名来匹配连接主机到 MySQL 授权表中的行。只能使用这些表中使用 IP 地址指定的帐户。（如果不存在指定客户端 IP 地址的帐户，则客户端可能无法连接。）

如果您有一个非常慢的 DNS 和许多主机，您可以通过启用[`跳过名称解析`](server-system-variables.html#sysvar_skip_name_resolve)禁用 DNS 查找，或通过增加[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)使主机缓存更大。

要完全禁止 TCP/IP 连接，请使用以下命令启动服务器[`跳过网络`](server-system-variables.html#sysvar_skip_networking)系统变量启用。

要在主机阻塞发生之前调整允许的连续连接错误数，请设置[`max_connect_errors`](server-system-variables.html#sysvar_max_connect_errors)系统变量。例如，要在启动时设置值，请将这些行放在服务器中`我的.cnf`文件：

```
[mysqld]
max_connect_errors=10000
```

要在运行时更改值，请执行以下操作：

```
SET GLOBAL max_connect_errors=10000;
```

##### 监控主机缓存

性能模式[`主机缓存`](performance-schema-host-cache-table.html)表公开主机缓存的内容。该表可以使用检查[`选择`](select.html)语句，它可以帮助您诊断连接问题的原因。有关此表的信息，请参阅[第 27.12.21.2 节，“主机\_缓存表”](performance-schema-host-cache-table.html).

##### 刷新主机缓存

在以下情况下，刷新主机缓存可能是可取的或可取的：

-   您的某些客户端主机更改了 IP 地址。

-   错误信息`主持人 '*`主机名`*' 被阻止`来自合法主机的连接发生。（看[处理被阻止的主机](host-cache.html#blocked-host).)

    刷新主机缓存具有以下效果：

-   它清除内存中的主机缓存。

-   它从性能模式中删除所有行[`主机缓存`](performance-schema-host-cache-table.html)公开缓存内容的表。

-   它取消阻止任何被阻止的主机。这允许来自这些主机的进一步连接尝试。

    要刷新主机缓存，请使用以下任一方法：

-   更改的值[`主机缓存大小`](server-system-variables.html#sysvar_host_cache_size)系统变量。这需要[`SYSTEM_VARIABLES_ADMIN`](privileges-provided.html#priv_system-variables-admin)特权（或已弃用的[`极好的`](privileges-provided.html#priv_super)特权）。

-   执行一个[`截断表`](truncate-table.html)截断性能模式的语句[`主机缓存`](performance-schema-host-cache-table.html)桌子。这需要[`降低`](privileges-provided.html#priv_drop)表的特权。

-   执行一个[`冲洗主机`](flush.html#flush-hosts)陈述。这需要[`重新加载`](privileges-provided.html#priv_reload)特权。

-   执行一个[**mysqladmin 刷新主机**](mysqladmin.html)命令。这需要[`降低`](privileges-provided.html#priv_drop)性能模式的特权[`主机缓存`](performance-schema-host-cache-table.html)表或[`重新加载`](privileges-provided.html#priv_reload)特权。

##### 处理被阻止的主机

[](<>)[](<>)

服务器使用主机缓存来跟踪客户端连接过程中发生的错误。如果出现以下错误，则表示[**mysqld**](mysqld.html)已收到来自给定主机的多个连接请求，这些请求中途中断：

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

价值[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)系统变量确定服务器在阻止主机之前允许的连续中断连接请求数。之后[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)失败的请求如果没有成功的连接，服务器会假定出现了问题（例如，有人试图闯入），并阻止主机进行进一步的连接请求。

要解除阻止主机，请刷新主机缓存；看见[刷新主机缓存](host-cache.html#host-cache-flushing).

或者，为了避免出现错误消息，设置[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)如中所述[配置主机缓存](host-cache.html#host-cache-configuration).的默认值[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)是100。增加的[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)如果设置为较大的值，则主机达到阈值并被阻止的可能性较小。然而，如果`主人的*`主机名`*“被封锁了。”`出现错误消息时，首先确认来自被阻止主机的TCP/IP连接没有问题。增加资产的价值是没有好处的[`最大连接错误`](server-system-variables.html#sysvar_max_connect_errors)如果有网络问题。
