現(xiàn)狀:我們的項目中使用了ofbiz2.1,并采用JotmFactory作為TransactionFactory,使用Oracle9i數(shù)據(jù)庫,在大并發(fā)測試的時候發(fā)現(xiàn)數(shù)據(jù)庫游標(biāo)暴漲并且不釋放,最終導(dǎo)致游標(biāo)溢出。
原因分析:ofbiz entityengine的很多操作都是使用PreparedStatement完成的,這無可厚非,問題是JotmFactory采用的是XAPool作為連接池,而XAPool對PreparedStatement進行了Cache,同時Oracle有一個出名的內(nèi)存漏洞,PreparedStatement使用之后必須關(guān)閉,如果不關(guān)閉連續(xù)進行SQL查詢會造成前面SQL的游標(biāo)不能釋放;此外JotmConnectionFactory沒有允許對XAPool做更多的配置,按照它使用XAPool的方式,XAPool會對PreparedStatement進行Cache。Oracle漏洞+ofbiz的不周全的使用方式+xapool的機制造成了游標(biāo)不釋放最終溢出的異常。
解決辦法:修改JotmConnectionFactory,調(diào)用StandardXAPoolDataSource的setPreparedStmtCacheSize(int)的方法,將preparedStmtCacheSize設(shè)置為0。需要注意的是xapool在目前的版本(1.4)當(dāng)preparedStmtCacheSize=0的時候存在一個bug,close PreparedStatement的時候會報NullPointerException,請參考我的另一個日志
XAPool1.4的bug。