使用 tomcat 6 dbcp 和 oracle 11 瘦驱动程序的堆空间不足
Posted
技术标签:
【中文标题】使用 tomcat 6 dbcp 和 oracle 11 瘦驱动程序的堆空间不足【英文标题】:Out of heap space with tomcat 6 dbcp and oracle 11 thin driver 【发布时间】:2011-03-23 23:34:34 【问题描述】:我在 Tomcat 6 上运行一个 Web 应用程序,使用 Tomcat DBCP 来管理 JDBC 连接。此应用程序可以与 mysql、SQL Server 一起运行,我们最近开始针对 Oracle 进行测试。与 MySQL 和 SQL Server 不同,当我们开始使用 Oracle 瘦驱动程序时,我们的应用程序开始使用无限内存。
应用程序在 Windows 2008 服务器上运行,并且安装了 Oracle 11g。 Tomcat 作为服务运行,最大内存为 2 gig,-XX:MaxPermSize=1024m,最大线程堆栈大小为 1024k。 DBCP 设置的最大活动数为 20,最大空闲数为 10。运行一段时间后,它将占用所有 2 个演出并开始报告:
java.lang.OutOfMemoryError: Java 堆空间
我们对 JDBC 的使用非常初级。我们从 JDBC 数据源获取连接,执行查询或更新,并在结果、语句和连接(如果每个都存在)上调用 close()。
当使用 MySQL 5 驱动程序或 JTDS 驱动程序运行时,我们可以在 1 gig 的内存中运行。唯一的区别是 Oracle 驱动程序。
我能做些什么来阻止这种情况?
更新(2011 年 3 月 30 日):我已添加 cmets 作为以下回复。有人可以帮忙吗?
以下是 cmets 的答案:
数据库与 Tomcat 不在同一台服务器上。托管 Tomcat 的服务器有 8 GB 的物理内存。
每次使用后我都不会关闭连接。我正在使用 Tomcat 的 DBCP,每次使用后都会调用 close(),但池设置为最大活动 20,最大空闲 10。
我运行的瘦驱动版本是11.2.0.2.0。
至于 -Xmx,我将其作为服务运行,“初始内存池”为 1024MB,“最大内存池”为 2048MB,“线程堆栈大小”为 1024KB
我没有堆栈跟踪 - 在内存不足错误之前没有错误(没有堆栈跟踪)。
【问题讨论】:
你能澄清一下,数据库和tomcat在同一个盒子上吗?盒子有多少内存,Oracle的目标内存是多少,Oracle实际使用了多少内存? 你真的是说每次使用后都会关闭连接吗? 另外,日志中真的没有更多信息吗?完整的 java 错误堆栈可能会有所帮助 这可能是特定版本驱动程序中的错误,但我认为您别无选择,只能在分析器下运行它并找出原因。-Xmx
设置的堆大小是多少,是 2 Gb
【参考方案1】:
这个答案可能很晚,但发布是为了帮助可能遇到类似情况的其他人。
在使用 JDBC 的应用程序运行期间遇到 OOME (OutOfMemoryError) 时,获取堆转储或多或少有助于解决问题的根本原因。在某些情况下,OOME 是自然抛出的,没有任何潜在的泄漏。这是由于堆本身已经耗尽。当执行 JDBC 语句返回较大的结果集时,可能会遇到这种情况。
Oracle JDBC 驱动程序在创建结果集时创建的对象显然很重,即使它们是短暂的(因为大多数应用程序在获取所需数据后不会保留对结果集的引用)。返回大量数据项(大量行或列)势必会导致这种情况。
如果是这种情况,可用于解决的唯一选项是:
增加 Java 堆的可用内存量。 尽可能重写查询以返回更小的数据集。可能还有其他潜在问题,但这些问题已经在其他问题中进行了足够详细的处理 - 例如,关闭结果集、语句和逻辑连接对象等。
【讨论】:
【参考方案2】:Vinet 的回答很好。这是一个很好的链接,解释了 11g 驱动程序的缓存策略以及为什么这个答案有意义:http://www.oracle.com/technetwork/database/enterprise-edition/memory.pdf。
如果查询的结果集非常大,则很可能是 jdbc 的缓存策略正在吞噬整个堆。我要添加到 Vinent 的答案中的唯一其他选项是设置最大缓存缓冲区大小。如果此值设置得太低,则会影响查询查找的性能。
【讨论】:
以上是关于使用 tomcat 6 dbcp 和 oracle 11 瘦驱动程序的堆空间不足的主要内容,如果未能解决你的问题,请参考以下文章
使用 Tomcat 7 新的连接池 —— Tomcat jdbc pool