現狀:我們的項目中使用了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。