【问题标题】:OOM due to Idle DB connections in Tomcat's ConnectionPool由于 Tomcat 连接池中的空闲数据库连接而导致 OOM
【发布时间】:2016-07-11 22:05:28
【问题描述】:

我正在使用 Tomcat 8.0.27、OpenJDK 8 更新 71 和 Oracle 11.2.0.3.0。驱动程序版本是 Oracle Database 11g 第 2 版 (11.2.0.3)。我遇到了OOM错误。

我深入到连接池对象,其中最大的对象是空闲连接列表:

放大空闲连接列表显示oracle.jdbc.driver.PhysicalConnection$BufferCacheStore持有的内存:

我的假设是这些缓冲区是由以前的连接持有者分配的,并且由于我的池配置允许容纳多达 30 个空闲连接,它们在达到空闲限制之前不会释放。

我的数据库池配置是:

  <bean id="dataSourcePoolProperties" class="org.apache.tomcat.jdbc.pool.PoolProperties">
                <property name="driverClassName">
                    <value>${db.driverClass}</value>
                </property>
                <property name="url">
                    <value>${db.url_prefix}:@${db.host}:${db.port}:${db.sid}</value>
                </property>
                <property name="username">
                    <value>${db.user}</value>
                </property>
                <property name="password">
                    <value>${db.password}</value>
                </property>
                <property name="maxActive">
                    <value>50</value>
                </property>
                <property name="maxIdle">
                    <value>30</value>
                </property>
                <property name="initialSize">
                    <value>10</value>
                </property>
                <property name="testOnBorrow">
                    <value>true</value>
                </property>
                <property name="testOnReturn">
                    <value>true</value>
                </property>
                <property name="validationQuery">
                    <value>select 1 from dual</value>
                </property>
                <property name="name">
                    <value>Main DataSource</value>
                </property>
                <property name="jmxEnabled">
                    <value>true</value>
                </property>
                <property name="logValidationErrors">
                    <value>true</value>
                </property>
            </bean>

我知道 Oracle 的驱动程序根据最大可能的查询大小分配缓冲区。检查他们的内容发现那里有许多零。

编辑 1:

Oracle 的驱动jar 文件在WEB-INF/lib 文件夹下,而tomcat-jdbc.jar 在CATALINA_HOME/lib 文件夹下。我知道这可能会给重新部署带来问题,但我们不这样做。

您能否建议一种关闭内部驱动程序缓冲区的方法?

【问题讨论】:

  • 是您的应用程序未正确释放其连接,还是即使未部署应用程序您也会遇到这种情况?
  • 由于连接位于空闲列表下,我假设应用程序正确释放它们。
  • 但是如果没有部署应用程序(或应用程序),您不会遇到这个问题,对吧?
  • 不,我们只部署一个应用程序。
  • 你的池配置是什么? (maxIdle、maxActive 等),您确定您的应用正在释放连接(正如 eis 已经询问的那样)?

标签: java jdbc tomcat8


【解决方案1】:

显然 OOM 是由于我们对驱动程序提取大小所做的更改,即每次提取时要检索的行数。随着每个大小 列和行数,驱动程序可以计算在一次提取中返回的数据的绝对最大大小。这可能是导致预分配缓冲区增长的原因。

仔细阅读 Oracle 的驱动文档发现

“11.2 驱动程序具有比 11.1.0.7.0 更复杂的缓冲区缓存。此缓冲区缓存具有 多个桶。桶中的所有缓冲区都具有相同的大小,并且该大小是预先确定的。 当第一次执行 PreparedStatement 时,驱动程序从存储桶中获取缓冲区 保存将保存结果的最小大小的缓冲区。如果桶中没有缓冲区,则 驱动程序分配与桶对应的预定义大小的新缓冲区。当一个 PreparedStatement 关闭,缓冲区返回到其相应的存储桶。由于缓冲区 用于一系列大小要求,缓冲区通常比 最低要求。”

回滚获取大小参数后,OOM 错误消失了。

【讨论】:

    猜你喜欢
    • 2014-12-04
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2013-03-22
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多