Alibaba Druid 数据库连接池 takeLast() AQS 死锁导致程序无响应

Alibaba Druid 数据库连接池 takeLast() AQS 死锁导致程序无响应

💡 原文中文,约1200字,阅读约需3分钟。
📝

内容提要

文章讨论了使用 Alibaba Druid 数据源时应用程序无响应的问题,主要由于线程在等待 `com.alibaba.druid.pool.DruidDataSource.takeLast()` 方法导致死锁。通过配置 `maxWait` 参数可以解决此问题,避免程序无限等待连接。默认情况下,`maxWait` 为 -1,表示无限等待。更新版本中对此进行了修正。

🔎

延伸解读

maxWait 默认值 -1 的风险

Druid 的 maxWait 参数默认值为 -1,表示从连接池获取连接时无限等待。当连接池耗尽时,线程会一直阻塞在 takeLast() 方法上,导致应用无响应且无错误日志。这种设计在连接泄漏或高并发场景下极易引发故障,因此生产环境应显式设置 maxWait 为一个合理值,避免无限等待。

死锁触发条件与堆栈特征

死锁发生在 maxWait <= 0 时,Druid 调用 takeLast() 而非 pollLast()。takeLast() 基于 AQS 实现,当无可用连接时线程进入 WAITING 状态。若连接池中的连接被长时间占用或泄漏,等待线程将无法被唤醒,形成死锁。通过堆栈可观察到大量线程阻塞在 takeLast() 方法,这是诊断该问题的关键线索。

版本差异与修复情况

文章指出在 Druid 1.2.17 版本中,maxWait 默认 -1 会导致无限等待。2024 年 1 月 23 日的提交(6ec6c006)修改了相关代码,可能改变了默认行为或增加了保护机制。使用旧版本的用户需自行配置 maxWait,而新版本用户可关注该提交的具体改动,以评估是否仍需显式设置。

❓

Q&A

为什么我的应用程序会无响应?

应用程序无响应主要是因为线程在等待 `com.alibaba.druid.pool.DruidDataSource.takeLast()` 方法导致死锁。

如何解决 Druid 数据库连接池的死锁问题?

通过在配置文件中设置 `maxWait` 参数,可以避免程序无限等待连接,从而解决死锁问题。

maxWait 参数的默认值是什么?

默认情况下,`maxWait` 的值为 -1,表示无限等待。

如何配置 maxWait 参数以避免程序无响应?

在配置文件中增加对 `maxWait` 的配置,设置一个正值即可避免程序无响应。

Druid 数据库连接池的最新版本是否修复了死锁问题?

是的,最新版本中对死锁问题进行了修正,代码已更新。

死锁发生时线程的状态是什么?

死锁发生时,大部分线程的状态为 WAITING,表示它们在等待连接。

🏷️

标签

➡️

继续阅读