本节还涵盖了相关的 Lost connection to server during query
错误。
出现 MySQL 服务器已断开连接
错误的最常见原因是服务器超时并关闭了连接。在这种情况下,您通常会收到以下错误代码(具体哪一个取决于操作系统)。
Error Code | Description |
---|---|
CR_SERVER_GONE_ERROR |
客户端无法将问题发送到服务器。 |
CR_SERVER_LOST |
客户端在写入服务器时没有收到错误,但没有收到完整的答案(或任何答案)。 |
默认情况下,服务器在八小时内没有任何活动后关闭连接。你可以通过设置 wait_timeout
变量来更改时间限制,当你启动 mysqld 时。见 第 7.1.8 节,“服务器系统变量”。
如果你有一个脚本,只需重新发出查询,以便客户端执行自动重新连接。这假设你已经在客户端启用了自动重新连接(这是 mysql
命令行客户端的默认设置)。
其他常见的 MySQL 服务器已断开连接
错误原因是:
-
你(或数据库管理员)使用
KILL
语句或 mysqladmin kill 命令杀死了正在运行的线程。 -
你尝试在关闭连接到服务器后运行查询。这表明应用程序中存在逻辑错误,应该被纠正。
-
客户端应用程序在不同的主机上运行,但没有从该主机连接到 MySQL 服务器的必要权限。
-
你在客户端遇到了 TCP/IP 连接超时。这可能发生在你使用以下命令时:
mysql_options(..., MYSQL_OPT_READ_TIMEOUT,...)
或mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT,...)
。在这种情况下,增加超时可能有助于解决问题。 -
你遇到了服务器端的超时,并且客户端中的自动重新连接被禁用(
MYSQL
结构中的reconnect
标志等于 0)。 -
你使用的是 Windows 客户端,服务器在命令发出之前已经断开了连接(可能是因为
wait_timeout
过期)。在 Windows 上的问题是,在某些情况下,MySQL 不会从操作系统中获取写入服务器的 TCP/IP 连接的错误,而是在尝试从连接中读取答案时获取错误。
解决方案是执行
mysql_ping()
在连接上,如果自上次查询以来已经过去了很长时间(这就是 Connector/ODBC 所做的),或者设置wait_timeout
在 mysqld 服务器上,使其在实践中从不超时。 -
你也可以在发送到服务器的查询无效或太大时遇到这些错误。如果 mysqld 收到一个太大或乱序的数据包,它将假设客户端出了问题,并关闭连接。如果你需要大查询(例如,如果你正在使用大
BLOB
列),你可以通过设置服务器的max_allowed_packet
变量来增加查询限制,该变量的默认值为 64MB。你可能还需要在客户端增加最大数据包大小。有关设置数据包大小的更多信息,请参见 第 B.3.2.8 节,“数据包太大”。一个
INSERT
或REPLACE
语句插入大量行也可能导致这种错误。无论插入多少行,这两个语句都将单个请求发送到服务器;因此,您可以通过减少每个INSERT
或REPLACE
的行数来避免错误。 -
如果主机名查找失败(例如,如果您的服务器或网络依赖的 DNS 服务器宕机),您也可能会看到这个错误。这是因为 MySQL 依赖于主机系统进行名称解析,但无法确定名称解析是否正常工作——从 MySQL 的角度来看,这个问题与任何其他网络超时无异。
如果 MySQL 以启用
skip_networking
系统变量的方式启动,您也可能会看到MySQL 服务器已消失
错误。另一个可能导致此错误的网络问题是,如果 MySQL 端口(默认为 3306)被防火墙阻止,从而阻止了对 MySQL 服务器的所有连接。
-
您还可能在使用 fork 子进程的应用程序中遇到此错误,其中每个子进程都尝试使用相同的连接来连接 MySQL 服务器。可以通过为每个子进程使用单独的连接来避免这种情况。
-
您遇到了服务器在执行查询时崩溃的错误。
您可以通过执行mysqladmin 版本并检查服务器的 uptime 来确定 MySQL 服务器是否崩溃并重新启动。如果客户端连接由于mysqld崩溃而断开,您应该集中于查找崩溃的原因。从检查查询是否再次杀死服务器开始。见第 B.3.3.3 节,“如果 MySQL Keeps Crashing”。
您可以通过以log_error_verbosity
系统变量设置为 3 启动mysqld来获取更多关于断开连接的信息。这将在hostname.err
文件中记录一些断开消息。见第 7.4.2 节,“错误日志”。
如果您想报告此问题的错误,请确保包括以下信息:
-
指出 MySQL 服务器是否崩溃。您可以在服务器错误日志中找到相关信息。见第 B.3.3.3 节,“如果 MySQL Keeps Crashing”。
-
如果特定查询杀死mysqld,并且在运行查询之前已经使用
CHECK TABLE
检查了相关表,可以提供一个可重现的测试用例吗?见第 7.9 节,“调试 MySQL”。 -
MySQL 服务器中的
wait_timeout
系统变量的值是什么?(mysqladmin 变量将给您这个变量的值。) -
您是否尝试过使用启用了通用查询日志的mysqld来确定问题查询是否出现在日志中?(见第 7.4.3 节,“通用查询日志”。)