You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby进程ActiveRecord连接池是否泄漏?v$session大量INACTIVE会话原因?

分析你的连接超时问题与INACTIVE会话疑问

首先直接回应你的核心问题:你的Ruby进程大概率存在连接池连接未正确归还的情况(也就是连接池泄漏),这才是触发ActiveRecord::ConnectionTimeoutError的根本原因;而v$session里的大量INACTIVE会话,大部分是连接池里的闲置复用连接,属于正常现象,但也可能夹杂着未归还的泄漏连接。

为什么判断可能有连接池泄漏?

你的database.yml里配置了pool: 20,意味着每个Ruby进程最多会创建20个数据库连接并放入连接池复用。8个进程理论上最多会有8*20=160个连接,当前总会话数78没到这个上限,但你却出现了连接超时——这说明某个(或多个)进程的连接池里,所有20个连接都被占用且未归还,导致该进程内的后续任务无法获取可用连接,等待5秒后触发超时。

你查询到只有7个ACTIVE会话,说明大部分连接其实处于闲置状态,但它们没有被放回连接池供后续任务使用,这就是典型的连接泄漏表现:连接被“占着茅坑不拉屎”,既不在执行SQL(INACTIVE),也不还给连接池复用。

为什么v$session里有大量INACTIVE会话?

Oracle的INACTIVE状态只是表示当前会话没有正在执行的SQL语句,并不代表连接已经被关闭或可以被复用。对于ActiveRecord的连接池来说:

  • 当任务使用完连接后,如果是通过块形式获取连接(比如ActiveRecord::Base.connection_pool.with_connection { |conn| ... }),连接会自动归还到连接池,此时对应的Oracle会话就会变成INACTIVE,等待下一次被复用。
  • 如果是手动获取连接(比如直接调用ActiveRecord::Base.connection)但没有主动调用ActiveRecord::Base.connection_pool.release_connection归还,这个连接就会一直被该线程占用,对应的Oracle会话也会保持INACTIVE状态,但连接池会认为它还在被使用,不会分配给其他任务。

所以你看到的71个INACTIVE会话里,一部分是正常的闲置复用连接,另一部分可能就是未被归还的泄漏连接。

排查与解决建议

  • 检查连接使用代码:排查所有手动获取数据库连接的地方,确保每次获取后都正确归还。优先使用块形式的连接调用(自动归还),避免手动操作连接。
  • 监控单个进程的连接池状态:在每个Ruby进程里添加日志或监控,输出ActiveRecord::Base.connection_pool.stat的结果,查看checked_out(已借出的连接数)、available(可用连接数)等指标。如果某个进程的checked_out长期等于20(pool的最大值),那肯定存在连接泄漏。
  • 调整连接池大小(谨慎操作):如果确认没有泄漏,但业务确实需要更多连接,可以适当调大pool值,但不要超过Oracle数据库允许的最大会话数限制,同时要考虑服务器的负载能力。
  • 排查长连接场景:如果你的计算任务存在长时间占用连接的情况(比如长时间的事务、未关闭的游标),也会导致连接无法及时归还,需要优化这类任务的逻辑,尽量缩短连接占用时间。

内容的提问来源于stack exchange,提问作者Vaibhav Dhoke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:52:11