Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关闭DruidDataSource时连接池停止增加新建连接 #4196

Merged
merged 1 commit into from
Mar 21, 2021

Conversation

zrlw
Copy link
Contributor

@zrlw zrlw commented Mar 14, 2021

check closed status before calling incrementPoolingCount()
@CLAassistant
Copy link

CLAassistant commented Mar 14, 2021

CLA assistant check
All committers have signed the CLA.

@caohdgege
Copy link

caohdgege commented Mar 21, 2021

这种方式是不是只能解决原本DruidDataSource已经连接成功了,然后需要切换到另一个数据库连接的情景。
但是解决不了DruidDataSource之前是连接失败的,但是一直在重试获取连接的情况?

如果是原本是连接失败的,close之后,CreateConnectionThread的线程卡在了死循环里面了,不停的想要创建连接,一直都创建失败

@zrlw
Copy link
Contributor Author

zrlw commented Mar 21, 2021

这种方式是不是只能解决原本DruidDataSource已经连接成功了,然后需要切换到另一个数据库连接的情景。
但是解决不了DruidDataSource之前是连接失败的,但是一直在重试获取连接的情况?

如果是原本是连接失败的,close之后,CreateConnectionThread的线程卡在了死循环里面了,不停的想要创建连接,一直都创建失败

  1. DruidDataSource执行close操作时会将CreateConnectionThread线程状态设为interrupt,CreateConnectionThread线程执行到await或sleep指令时就会抛interrupt异常而进行到线程退出处理。
  2. 无限次尝试获取连接是Druid连接池的默认操作,除非你将breakAfterAcquireFailure设置为true,否则会一直尝试获取连接。但是设置为true之后,一旦获取数据库连接失败,数据库之后就算恢复正常了,Druid连接池也不会自动重连(因为CreateConnectionThread线程已经退出),要手工重启应用才行(重启CreateConnectionThread线程),所以大多数场景下都不应该把这个参数设置为true。

@caohdgege
Copy link

这种方式是不是只能解决原本DruidDataSource已经连接成功了,然后需要切换到另一个数据库连接的情景。
但是解决不了DruidDataSource之前是连接失败的,但是一直在重试获取连接的情况?
如果是原本是连接失败的,close之后,CreateConnectionThread的线程卡在了死循环里面了,不停的想要创建连接,一直都创建失败

  1. DruidDataSource执行close操作时会将CreateConnectionThread线程状态设为interrupt,CreateConnectionThread线程执行到await或sleep指令时就会抛interrupt异常而进行到线程退出处理。
  2. 无限次尝试获取连接是Druid连接池的默认操作,除非你将breakAfterAcquireFailure设置为true,否则会一直尝试获取连接。但是设置为true之后,一旦获取数据库连接失败,数据库之后就算恢复正常了,Druid连接池也不会自动重连(因为CreateConnectionThread线程已经退出),要手工重启应用才行(重启CreateConnectionThread线程),所以大多数场景下都不应该把这个参数设置为true。

好的,谢谢解答。

@Bobo1553
Copy link

Bobo1553 commented Jul 1, 2024

我最近也碰到了类似的问题,DruidDataSource之前是连接失败的,DruidDataSource Close之后,CreateConnectionThread没有退出,初步排查了一下,是close方法会将CreateConnectionThread的线程状态设置为interrupt,但是不知道为啥(没定位到),这个interrupt的线程状态没有被InterruptedException捕获就被设置false了,导致CreateConnectionThread没法退出,一直在重复创建连接

复现方法:
Druid版本1.2.14

  1. 启动一个Druid DataSource,连接上正常的MySQL
  2. Kill掉这个MySQL
  3. 发起一个业务查询,这时候Druid会一直报创建连接失败(符合预期)
  4. 关闭Druid的数据源,可以明确看到日志Druid closed,但是,后台创建连接的线程没有中断,还是一直在报连接失败...(很大概率)

@nuaaguojin
Copy link

我最近也碰到了类似的问题,DruidDataSource之前是连接失败的,DruidDataSource Close之后,CreateConnectionThread没有退出,初步排查了一下,是close方法会将CreateConnectionThread的线程状态设置为interrupt,但是不知道为啥(没定位到),这个interrupt的线程状态没有被InterruptedException捕获就被设置false了,导致CreateConnectionThread没法退出,一直在重复创建连接

复现方法: Druid版本1.2.14

  1. 启动一个Druid DataSource,连接上正常的MySQL
  2. Kill掉这个MySQL
  3. 发起一个业务查询,这时候Druid会一直报创建连接失败(符合预期)
  4. 关闭Druid的数据源,可以明确看到日志Druid closed,但是,后台创建连接的线程没有中断,还是一直在报连接失败...(很大概率)

找到问题了。com.mysql.jdbc.ConnectionImpl#connectWithRetries 中 把InterruptedException异常吃掉了。没有重设中断标志位,导致druid上层没捕捉到中断标志
if (attemptCount > 0) {
try {
Thread.sleep((long) timeout * 1000);
} catch (InterruptedException IE) {
// ignore
}
}
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants