Communications link failure The last packet successfully received from the server was 7,304,270 milliseconds ago 报错

1.tidb版本 5.7.25-TiDB-v3.0.2

2.问题描述 数据统计逻辑: 每天零点汇总前一天的数据,任务是分客户Id去并行处理的,零点大概有5~6个大数据量的客户数据去处理和一批小数据量客户,大数据量的客户天表的数据大概在500w,汇总完(group by一系列字段)数据大概在300w。小数据的客户只有少量数据,通过springbatch 分页去处理,读10w,写入1w。在这个任务执行过程中,发现报大量如下错误:

Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 7,304,270 milliseconds ago. The last packet sent successfully to the server was 7,304,250 milliseconds ago. ; SQL []; Communications link failure

3.通过查询tidb资料,得到一个大概信息是:当tidb负载过高时,会自动关闭掉一些链接,客户端并不知道这个链接已经被关闭,导致再次通过这个链接去请求时,发现已经链接已经关闭,报Communications link failure 错误,现不知道这个结论是否正确,以及是否有参数调优、优化的实践。

这应该是业务侧的报错吧,可以看下 tidb 的日志,是否是集群发生 oom 导致,如果发生 oom ,可参考 tug 其他 oom 帖子解决该问题。

另外,集群 tidb 负载过高,也不会自动关闭链接的。如出现此类情况,可能集群此时处于异常情况。

业务端代码跟其他任务代码并没有区别,这个问题只在特定条件下才会出现,统计一整天的数据才会有,统计每小时不会出现。而且,是在批量数据的过程中出现,比如500w数据,读第10页的时候出现。

  1. 可以检查一下报错时间段,tidb 节点有没有发生过重启
  2. 对于应用连接池可以配置一下心跳检测,固定一段时间检测一下连接是否可用
  3. 对连接池设置自动重连机制

– 配置获取连接等待超时的时间

spring.datasource.maxWait=120000

– 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

spring.datasource.timeBetweenEvictionRunsMillis=60000

– 配置一个连接在池中最小生存的时间,单位是毫秒

spring.datasource.minEvictableIdleTimeMillis=180000

spring.datasource.validationQuery=SELECT 1 FROM DUAL

spring.datasource.testWhileIdle=true

spring.datasource.testOnBorrow=true

spring.datasource.testOnReturn=false

spring.datasource.keepAlive=true

这些配置都有设置

  1. 检查一下报错时间段,tidb 节点有没有发生重启
  2. 检查一下 tidb 中 wait_timeout 和 interactive_timeout 参数配置
  3. 检查一下 Linux内核 tcp 连接相关参数
  4. 有配置负载均衡吗,是使用的什么?有可以检查一下负载均衡相关的配置

因为这个错误对于应用程序来说就是在使用连接去访问数据库时,发现数据库已经将这个链接断开了,所以排查可以按照链路上的环节进行排查一下

请问这个问题解决了吗? 若已解决,能否告知是如何解决的?

首先,TiDB 并没有在压力下主动断开一些连接的机制。 可以尝试开启连接池上的 testonborrow 功能,它的原理是定时在客户端发送心跳给数据库服务端,防止连接太久没有相应而(被连接池/LB/网络等)断开。