OOM由于Tomcat的ConnectionPool中的空闲数据库连接

时间:2016-03-24 10:33:43

标签: java jdbc tomcat8

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

Memory Leak Detector

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

Tomcat Pooled Connections

缩放到空闲连接列表显示由 oracle.jdbc.driver.PhysicalConnection $ BufferCacheStore 保存的内存:

Idle connection list

PhysicalConnection

我的假设是这些缓冲区是由之前的连接持有者分配的,因为我的池配置允许最多容纳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文件夹下。我知道这可能会对重新部署造成问题,但我们不这样做。

你能建议一种解除内部驱动缓冲区的方法吗?

1 个答案:

答案 0 :(得分:0)

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

仔细阅读Oracle的驱动程序文档显示

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

回滚fetch size参数后,OOM错误消失了。