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)
抓包如下,
image.png
正常关闭连接
正常的关闭连接会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包,抓包如下:
image.png
网友评论