代码改变世界

MySQL报Got timeout writing communication packets错误

2023-03-12 15:07  abce  阅读(1560)  评论(0编辑  收藏  举报

应用日志显示连接数据库超时,查看MySQL的错误日志,发现大量的如下错误:

2023-02-14T14:19:48.330743+08:00 696688 [Note] [MY-010914] [Server] Aborted connection 696688 to db: 'abce' user: 'abce' host: '19.19.19.18' (Got timeout writing communication packets).
2023-02-14T14:20:55.911237+08:00 697898 [Note] [MY-010914] [Server] Aborted connection 697898 to db: 'abce' user: 'abce' host: '19.19.19.172' (Got an error reading communication packets).
2023-02-14T14:25:31.417976+08:00 701674 [Note] [MY-010914] [Server] Aborted connection 701674 to db: 'abce' user: 'abce' host: '19.19.19.228' (Got timeout writing communication packets).
2023-02-14T14:25:31.794582+08:00 695976 [Note] [MY-010914] [Server] Aborted connection 695976 to db: 'abce' user: 'abce' host: '19.19.19.228' (Got timeout writing communication packets).
2023-02-14T14:26:43.106000+08:00 707258 [Note] [MY-010914] [Server] Aborted connection 707258 to db: 'abce' user: 'abce' host: '19.19.19.228' (Got timeout writing communication packets).
2023-02-14T14:29:36.373428+08:00 709051 [Note] [MY-010914] [Server] Aborted connection 709051 to db: 'abce' user: 'abce' host: '19.19.19.18' (Got timeout writing communication packets).
2023-02-14T14:37:15.716545+08:00 709222 [Note] [MY-010914] [Server] Aborted connection 709222 to db: 'abce' user: 'abce' host: '19.19.19.228' (Got timeout writing communication packets).
2023-02-14T14:37:36.151345+08:00 710054 [Note] [MY-010914] [Server] Aborted connection 710054 to db: 'abce' user: 'abce' host: '19.19.19.18' (Got timeout writing communication packets).
2023-02-14T14:40:36.133651+08:00 715894 [Note] [MY-010914] [Server] Aborted connection 715894 to db: 'abce' user: 'abce' host: '19.19.19.18' (Got timeout writing communication packets).
2023-02-14T14:40:48.797275+08:00 700920 [Note] [MY-010914] [Server] Aborted connection 700920 to db: 'abce' user: 'abce' host: '19.19.19.172' (Got an error reading communication packets).
2023-02-14T14:40:48.797316+08:00 700669 [Note] [MY-010914] [Server] Aborted connection 700669 to db: 'abce' user: 'abce' host: '19.19.19.172' (Got an error reading communication packets).

解决方案:

>show variables like '%timeout%';
+-----------------------------------+----------+
| Variable_name                     | Value    |
+-----------------------------------+----------+
| connect_timeout                   | 10       |
| delayed_insert_timeout            | 300      |
| have_statement_timeout            | YES      |
| innodb_flush_log_at_timeout       | 1        |
| innodb_lock_wait_timeout          | 10       |
| innodb_rollback_on_timeout        | ON       |
| interactive_timeout               | 1800     |
| lock_wait_timeout                 | 1800     |
| mysqlx_connect_timeout            | 30       |
| mysqlx_idle_worker_thread_timeout | 60       |
| mysqlx_interactive_timeout        | 28800    |
| mysqlx_port_open_timeout          | 0        |
| mysqlx_read_timeout               | 30       |
| mysqlx_wait_timeout               | 28800    |
| mysqlx_write_timeout              | 60       |
| net_read_timeout                  | 30       |
| net_write_timeout                 | 60       |
| replica_net_timeout               | 60       |
| rpl_stop_replica_timeout          | 31536000 |
| rpl_stop_slave_timeout            | 31536000 |
| slave_net_timeout                 | 60       |
| ssl_session_cache_timeout         | 300      |
| wait_timeout                      | 1800     |
+-----------------------------------+----------+
 
>set global net_write_timeout=240;

 

MySQL在不同的阶段使用了不同的超时变量。例如:
·当连接刚刚建立时,使用connect_timeout
·当服务器等待另一个查询发送给它使用wait_timeout(或interactive_timeout,用于交互式的应用程序)。这里的超时设置一般比较大
·如果正在读取查询或正在返回结果集,则使用更短的net_read_timeout和net_write_timeout

net_read_timeout很少会成为问题,除非你的网络非常差。在大多数情况下,查询生成并作为单个数据包发送到服务器,应用程序不能切换做其他事情、也不能让服务器接收部分查询。

但是结果集返回可以分为多个部分,如果你使用mysql_use_result,在多次获取获取结果之间,你可以做任何工作,这可能会花很多时间,所以增加net_write_timeout可能是一个好主意。

你可能会问,为什么服务器不做任何流量控制,不能发现客户端只是忙,而不是网络问题-好吧,这来自于MySQL协议的简单性,它不允许客户端与服务器交谈,直到获取完整的结果集。这也是为什么你不能停止普通语句的获取过程的原因,mysql_free_result必须完成获取。

由于net_write_timeout和net_read_timeout是会话级别的变量,你可以简单地为每个可能有超时问题的连接更改它们。

因此:
·如果是认证过程中超时,都是connect_timeout;
·对于读网络超时,一般是wait_timeout/interactive_timeout,基本不会是net_read_timeout(特例是业务用到LOAD DATA LOCAL FILE)
·对于写网络超时,都是net_write_timeout。


Aborted connection报错一般分两种,
(1)Got an error reading communication packets,基本是网络等原因导致。
(2)Got timeout reading communication packets,原因基本是会话的idle时间达到了数据库指定的timeout时间。


在遇到超时情况下,可以根据这些原则判断对那个参数做调整。

比如下面这种情况:

[Warning] Aborted connection 6 to db: 'unconnected' user: 'root' host: 'localhost' (Got timeout reading communication packets)

很可能需要调整的 wait_timeout/interactive_timeout。

 

[Warning] Aborted connection 12 to db: 'test' user: 'root' host: 'localhost' (Got timeout writing communication packets)

需要调整 net_write_timeout

 

需要注意的是,MySQL 的关于网络的错误,除了超时以外都认为是 error,没有做进一步的细分,比如可能会看到下面这种日志,有可能是客户端异常退出了,也有可能是网络链路异常。

[Warning] Aborted connection 8 to db: 'unconnected' user: 'root' host: 'localhost' (Got an error reading communication packets)

[Warning] Aborted connection 13 to db: 'test' user: 'root' host: 'localhost' (Got an error writing communication packets)