项目运行许久,突然经常性的提示这个异常,过一段时间就会自己恢复,记录一下排查的过程
Communications link failure:通信链路故障,就是数据库连接异常。
所以排查思路大致如下:
1、检查数据库是否能正常登录使用
2、数据库是否有过升级?可能是连接驱动的问题?参考:
[已解决]踩过的坑之mysql连接报“Communications link failure”错误-腾讯云开发者社区-腾讯云
3、可能是代码中连接数过多,频繁请求(多线程)导致数据库拒绝连接?
在当前项目部署环境下查看特定数据库地址的网络连接情况:
netstat - anop | grep ip:port
查看后发现大量的数据库TIMA_WAIT,这个属于频繁的短连接,一般情况下是正常的,但这里如果在多线程中使用连接,需要注意可能会耗尽资源,导致数据库拒接连接,同时也伴随着出现如下问题
'ip' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'"
这个异常是只当前ip因为多次连接错误,被mysql拒绝访问,可以通过 mysqladmin flush-hosts
的命令刷新,解除该ip的的限制,但这只是一个暂时性的解决方法,除此之外如果在检查过代码没问题外,还有几种解决方式:
①、调整 MySQL 的 max_connect_errors
参数(暂时)
SHOW VARIABLES LIKE 'max_connect_errors'; //查看当前的
max_connect_errors
值SET GLOBAL max_connect_errors = 1000; //修改
max_connect_errors
的值
②、编辑 MySQL 的配置文件/etc/mysql/my.cnf(永久)
在my.cnf中的[mysqld]下添加配置,然后重启 systemctl restart mysqld
max_connect_errors = 1000;
③、调整数据库连接池的大小
④、数据库增加定时器,定期刷新hosts;
参考:Mysql使用定时器自动执行FLUSH HOSTS处理_flush hosts;-CSDN博客
但以上的解决方式只是暂时的,并没有找到问题的根源
4、可能是数据库数据量过大,或者sql语句引起的问题
①、查询慢sql日志
②、explain sql 分析查询范围
③、数据量大进行迁移或者分库分表
5、网络波动导致连接不稳定
①、通过一个简单的脚本检测tcp的连接,检测结果记录在日志中
#!/bin/bash
IPS=(
"ip:port"
"ip:port"
)LOG_FILE="/home/tcp_check.log"
while true;do
CURRENT_TIME=$(date +"%Y-%m-%d %H:%M:%S")
for IP_PORT in "${IPS[@]}";do
IP=$(echo "$IP_PORT" | cut -d':' -f1)
PORT=$(echo "$IP_PORT" | cut -d':' -f2)
if timeout 3 bash -c "cat < /dev/null> /dev/tcp/$IP/$PORT" 2>/dev/null; then
STATUS="成功"
else
STATUS="失败"
fi
echo "[$CURRENT_TIME] 检测 $IP:$PORT 的状态:$STATUS" >> "$LOG_FILE"
done
sleep 1
done
经过记录后发现,在代码报错的时候,此记录均为成功状态,ping也是成功的,但用telnet时发现连接是不成功的,所以这个脚本只检查tcp连接,无法判断服务器是否有响应。
②、可能是握手协议没完成,导致应用接收到异常。这时候再看“Host 'xxx' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'”这个错误时,通过查阅,了解到一个mysql的参数:max_connect_errors
参考文章:MySQL参数max_connect_errors分析释疑 - 潇湘隐者 - 博客园
且host_cache的字段是统计被视为“阻塞”的连接错误的数量(根据max_connect_errors系统变量进行评估)。 只计算协议握手错误,并且仅用于通过验证的主机(HOST_VALIDATED = YES)。
所以超过连接超时的时间范围内,握手协议未完成后,就会记录一次SUM_CONNECT_ERRORS,且COUNT_HANDSHAKE_ERRORS也增加一次。
所以综上所述,由于网络不稳定,导致客户端与数据库之间连接的握手协议没有完成,导致发生Communications link failure 和 ip is blocked because of many connection errors两个错误,就算解决掉blocked的错误后,握手协议不完成,依旧会连接失败,再加上线程池的使用,一个线程失败后,需要等到池里的连接过时才会继续连接,就会出现时好时坏的现象了
最终的网络问题还需要专业的人员解决。。。