mysql数据库链接中断_mysql 数据库链接中断报错分析

一、背景

Mysql 的DBA给Mysql定义一套规则,mysql 服务器端的默认的超时时间wait_timeout为8小时,但DBA把wait_timeout改为600秒,我估计这规则本意是减少数据库的长时间链接的情况,只要链接空闲超过600秒,服务器端会自动断开链接。所有产生的影响必须由客户端程序来保障。

1.1、版本说明:

mysql:5.7.17

druid:1.1.5

mysql-connector-java:5.1.44

1.2、druid重要属性配置

二、现象

系统上线一段时间后,在监控时而报错如下:

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

The last packet successfully received from the server was 72,557 milliseconds ago. The last packet sent successfully to the server was 0 milliseconds ago.

根据错误日志初步判断肯定是 mysql服务端把链接已经断开,但客户端不知道并,依然尝试使用了一个已经断开的链接才会引起这个错误发生。但是根据我们对 druid 了解,druid 有链接检查功能,按理不会拿到一个无效链接才对。

三、分析

3.1、整体分析

e7a1300f4250

image.png

图片表示了druid在获取线程池的大致的逻辑过程:druid在初始化时会创建两个守护线程,分别承担线程的创建(CreateConnectionThread)和销毁任务(DestoryConnectionThread),

当用户线程出现等待获取线程的操作时(且线程池中的线程数不大于最大活动线程数),创建线程会自动创建新的连接并放到线程池中,所以当用户线程需要新的连接时,只需要直接从线程池获取即可。

当用户线程从线程池中获取到连接会根据用户的配置决定是否线程进行有效性验证,如果验证线程有效则返回线程,如果无效则将该连接关闭,(DestoryConnectionThread自动回收已关闭的连接)

3.2、线程创建及销毁任务

程序启动在创建数据连接时,会自动创建两个任务(job),也就是CreateConnectionThread和DestoryConnectionThread

CreateConnectionThread比较简单,也是个守候线程,代码如下:

public class CreateConnectionThread extends Thread {

public CreateConnectionThread(String name){

super(name);

this.setDaemon(true);

}

public void run() {

initedLatch.countDown();

long lastDiscardCount = 0;

int errorCount = 0;

for (;;) {

// addLast

try {

lock.lockInterruptibly();

} catch (InterruptedException e2) {

break;

}

long discardCount = DruidDataSource.this.discardCount;

boolean discardChanged = discardCount - lastDiscardCount > 0;

lastDiscardCount = discardCount;

try {

boolean emptyWait = true;

if (createError != null

&& poolingCount == 0

&& !discardChanged) {

emptyWait = false;

}

if (emptyWait

&& asyncInit && createCount < initialSize) {

emptyWait = false;

}

if (emptyWait) {

// 必须存在线程等待,才创建连接

if (poolingCount >= notEmptyWaitThreadCount //

&& (!(keepAlive && activeCount + poolingCount < minIdle))

&& !isFailContinuous()

) {

empty.await();

}

// 防止创建超过maxActive数量的连接

if (activeCount + poolingCount >= maxActive) {

empty.await();

continue;

}

}

} catch (InterruptedException e) {

lastCreateError = e;

lastErrorTimeMillis = System.currentTimeMillis();

if (!closing) {

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值