现状:我们的项目中使用了ofbiz2.1,并采用JotmFactory作为TransactionFactory,使用Oracle9i数据库,在大并发测试的时候发现数据库游标暴涨并且不释放,最终导致游标溢出。
原因分析:ofbiz entityengine的很多操作都是使用PreparedStatement完成的,这无可厚非,问题是JotmFactory采用的是XAPool作为连接池,而XAPool对PreparedStatement进行了Cache,同时Oracle有一个出名的内存漏洞,PreparedStatement使用之后必须关闭,如果不关闭连续进行SQL查询会造成前面SQL的游标不能释放;此外JotmConnectionFactory没有允许对XAPool做更多的配置,按照它使用XAPool的方式,XAPool会对PreparedStatement进行Cache。Oracle漏洞+ofbiz的不周全的使用方式+xapool的机制造成了游标不释放最终溢出的异常。
解决办法:修改JotmConnectionFactory,调用StandardXAPoolDataSource的setPreparedStmtCacheSize(int)的方法,将preparedStmtCacheSize设置为0。需要注意的是xapool在目前的版本(1.4)当preparedStmtCacheSize=0的时候存在一个bug,close PreparedStatement的时候会报NullPointerException,请参考我的另一个日志
XAPool1.4的bug。