当前位置: 首页 > news >正文

数据库主从切换过程中Druid没法获取连接错误

背景:

今天dba在进行DB的主从切换,导致应用一直报错,获取不到DB连接,druid的错误信息如下:

Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 15000, active 20

可以看到活跃连接数active=20, 而应用配置中设置的maxActive=100,远远没有达到最大的连接数,为什么就创建不了连接呢?

查找真相

查看和db连接有关的错误日志,发现如下

ERROR com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread (DruidDataSource.java:1713) - create connection holder error
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 0 milliseconds ago. 

错误信息展示CreateConnectionThread 创建连接线程报错,那问题就变成了猜测连接线程已经被中止了,导致没法创建连接,使用jstack命令导出应用线程,发现确实CreateConnectionThread 线程确实不存在了,所以问题已经明朗,是因为CreateConnectionThread 线程中止了,导致再也无法创建连接。

对CreateConnectionThread 线程的代码进行检查:

public void run() {initedLatch.countDown();int errorCount = 0;for (;;) {// addLasttry {lock.lockInterruptibly();} catch (InterruptedException e2) {break;}try {// 必须存在线程等待,才创建连接if (poolingCount >= notEmptyWaitThreadCount) {empty.await();}// 防止创建超过maxActive数量的连接if (activeCount + poolingCount >= maxActive) {empty.await();continue;}} catch (InterruptedException e) {lastCreateError = e;lastErrorTimeMillis = System.currentTimeMillis();break;} finally {lock.unlock();}Connection connection = null;try {connection = createPhysicalConnection();} catch (SQLException e) {LOG.error("create connection error", e);errorCount++;if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {if (breakAfterAcquireFailure) {break;}try {Thread.sleep(timeBetweenConnectErrorMillis);} catch (InterruptedException interruptEx) {break;}}} catch (RuntimeException e) {LOG.error("create connection error", e);continue;} catch (Error e) {LOG.error("create connection error", e);break;}if (connection == null) {continue;}DruidConnectionHolder holder = null;try {holder = new DruidConnectionHolder(DruidDataSource.this, connection);} catch (SQLException ex) {// 主从切换过程中,这里有报错,导致线程中止LOG.error("create connection holder error", ex);break;}lock.lock();try {connections[poolingCount++] = holder;if (poolingCount > poolingPeak) {poolingPeak = poolingCount;poolingPeakTime = System.currentTimeMillis();}errorCount = 0; // reset errorCountnotEmpty.signal();notEmptySignalCount++;} finally {lock.unlock();}}}
}

我使用的版本是druid 1.7,升级到最新的1.15版本后,这个bug已经没有解决了

http://www.lryc.cn/news/196556.html

相关文章:

  • 【iOS】Mac M1安装iPhone及iPad的app时设置问题
  • Springboot 启动报错@spring.active@解析错误
  • 【算法挨揍日记】day15——560. 和为 K 的子数组、974. 和可被 K 整除的子数组
  • 数字时代的探索与革新:Socks5代理的引领作用
  • 算法-堆/归并排序-排序链表
  • word 如何编写4x4矩阵
  • INTELlij IDEA编辑VUE项目
  • linux进程间通讯--信号量
  • VS Code连接远程Linux服务器开发c++项目
  • stable diffusion的模型选择,采样器选择,关键词
  • BI零售数据分析:以自身视角展开分析
  • Maven 使用教程(三)
  • 行秋找工作的记录
  • vue项目打包,使用externals抽离公共的第三方库
  • 九阳真经之各大厂校招
  • Go语言入门心法(五): 函数
  • gitignore文件的语法规则
  • vscode提示扩展主机在过去5分钟内意外终止了3次,解决方法
  • 【算法挨揍日记】day16——525. 连续数组、1314. 矩阵区域和
  • k8s-13 存储之secret
  • 什么是高阶成分(HOC)
  • 深度学习硬件配置推荐
  • 数仓建设(一)
  • Springboot整合taos时序数据库TDengine
  • Epoch、批量大小、迭代次数
  • qt-C++笔记之清空QVBoxLayout中的QCheckBox
  • pc微信39223部分算法call偏移
  • 尚硅谷Flink(三)时间、窗口
  • MPLS基础
  • react+antd+Table实现表格初始化勾选某条数据,分页切换保留上一页勾选的数据