vlambda博客
学习文章列表

DBA你来下,连接MySQL报错啦!

客户端连接MySQL出现ERROR 2013 (HY000): Lost connection to MySQL server at 'reading authorization packet', system error: 0错误,是什么原因呢?

检查账号

确认授权账号的主机

确保授权账号的主机是包含所连接客户端的,主机部分可以使用%_符号来进行模糊匹配,使用以下命令检查授权的账号(如查询datax开头的授权账号):

SELECT user,host from mysql.user \
WHERE user like 'datax%';

使用以下命令检查账号的权限:

SHOW GRANTS FOR 'datax'@'10.%';

检查是否有开启反向DNS解析

抓包分析

在该场景中,使用telnet 命令检查是可以建立连接的,用MySQL客户端进行测试发现报上述的错误。在MySQL端使用tcpdump命令进行抓包,检查详细的问题。tcpdump命令:

tcpdump host 10.0.130.161 \
        -vv -i bond4 -n \
        -w 130161.cap

使用wireshark打开所抓取的包后,发现出现TCP Dup ACK包,且在10s后数据库服务器端发送RST断开连接:

通过检查MySQL的连接超时参数(connect_timeout)发现配置的是10s,通过调大到120s(因跨地域访问进行数据迁移),MySQL客户端可以连接到服务端了。

SHOW VARIABLES LIKE 'connect_timeout';
SET GLOBAL connect_timeout=120;

修改连接超时时间后在客户端和MySQL服务器端进行抓包,发现 从客户端到服务端存在数据丢包重传。客户端的抓包:DBA你来下,连接MySQL报错啦!

服务端的抓包:DBA你来下,连接MySQL报错啦!

TCP重传

当数据包在超时时间后(Linux RTO影响参数tcp_retries1和tcp_retries2[1])没收到ACK回复时,会成倍RTO的间隔时间进行重传,一直到设置的限制值,可以参考TCP-聊一聊重传次数[2]

如上图抓包,一直重传了8次,到14号包(33.883129s时)重传第八个包,服务端才收到,如下图。DBA你来下,连接MySQL报错啦!

后来通过网络大神在网络设备上进行包补偿来优化解决这个问题,抓包后发现,在服务器上看不到重传包的问题:DBA你来下,连接MySQL报错啦!

MySQL认证流程

通过抓包,可以看到先会经过三次握手建立连接,然后MySQL服务端发一个认证包(有服务器版本、字符集等信息),客户端随后响应包含用户名和密码的认证包,服务端进行验证,并返回一个应答。

认证流程堆栈如:

参考资料

[1]

sysctl: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

[2]

TCP-聊一聊重传次数: https://www.jianshu.com/p/d865c7f8b1e6