MySQL报错:Got an error reading communication packets

error reading 关闭连接

通常一旦连接建立,MySQLD端的线程会堵塞在poll上,而poll的就是连接socket的fd,等待读取命令,也就是读取MySQL net packet的header。同时如果是poll timeout超时则设置为SOCKET_ETIMEDOUT 这就是我们平时说的wait_timeout参数如下:

net_read_packet_header
 ->net_read_raw_loop
   ->vio_read
     ->vio_socket_io_wait
       ->vio_io_wait
         -> poll

net_read_raw_loop会循环读取需要的字节数量,而MySQL net packet就是4个字节,一旦poll检测到数据达到,则会从vio_socket_io_wait中return 0,然后调用mysql_socket_recv从socketfd中读取数据。如果read socket读取到为0字节,那么通常代表是客户端发送了fin包,注释如下:

/* Zero indicates end of file. */

这个时候因为没有读取到预期的4字节,那么就会进入判定流程,如果不是
SOCKET_ETIMEDOUT,也就是不是poll超时,那么就会报错ER_NET_READ_ERROR也就是看到的read error,如果是超时就是read timeout,对应的错误如下:

  • Got an error reading communication packets

最终会error层层返回后在handle_connection函数中调用close关闭socket,返回客户端fin包。这种情况通常当应用crash,操作系统会帮应用发送最后的fin包,但是这个时候不会有COM_QUIT包,测试可以直接kill -9 mysql客户端进行就可以了,

2023-05-10T03:02:46.728236Z 5 [Note] Aborted connection 5 to db: 'unconnected' user: 'root' host: 'mgr1' (Got an error reading communication packets)
2023-05-10T03:03:11.466218Z 6 [Note] Aborted connection 6 to db: 'unconnected' user: 'root' host: 'mgr1' (Got an error reading communication packets)
2023-05-10T03:04:19.929097Z 7 [Note] Aborted connection 7 to db: 'unconnected' user: 'root' host: 'mgr1' (Got an error reading communication packets)
2023-05-10T03:04:56.230077Z 8 [Note] Aborted connection 8 to db: 'unconnected' user: 'root' host: 'mgr1' (Got an error reading communication packets)

抓包如下,

正常关闭连接

正常的关闭连接会poll会检测到有包到达,且read socket读取到的为
COM_QUIT的包,会正常终止socket连接,并且终止之前不可能再去poll操作和read socket fd了,如下

  case COM_QUIT:
    /* We don't calculate statistics for this command */
    query_logger.general_log_print(thd, command, NullS);
    // Don't give 'abort' message
    // TODO: access of protocol_classic should be removed
    if (thd->is_classic_protocol())
      thd->get_protocol_classic()->get_net()->error= 0;
    thd->get_stmt_da()->disable_status();       // Don't send anything back
    error=TRUE;                 // End server
    break;

也就是不在进行socket通道的poll和read操作,自然不会在读取包了。在handle_connection函数中调用close关闭socket,返回客户端fin包。
这个时候会发现有COM_QUIT包,抓包如下:

猜你喜欢

转载自blog.csdn.net/quanzhan_King/article/details/130676786