WebSphere數據源中的連接被意外關閉案例

頻繁創建連接的現象

前陣子維護反饋說,oracle數據庫每秒創建連接數過高,而主要來源來自於WebSphere集羣所在的主機。
按理說,使用連接池的應用,連接是不會很頻繁的。追溯一下所在主機的程序,發現可疑對象是一個使用jdbc輪子的應用。
就是自己寫了一套代碼封裝了jdbc操作,雖然連接是從數據源中獲取的。

但是,單純看代碼,的確沒發現有什麼問題,該關閉的地方也關閉,不存在泄露的情況。再說,這種現象也不是泄露的表現。
另外,由於生產上的數據庫連接串,開發人員是沒有的,所以生成都是通過jndi的方式來處理的,不存在盜鏈的代碼。

不過,我們還是在日誌裏邊發現一些問題。在SystemOut的日誌裏邊,頻繁出現類似下面的異常信息:

[12-2-27 9:01:29:262 GMT+08:00] 00000038 MCWrapper     E   J2CA0081E: 
嘗試對資源 ecareDB 的 ManagedConnection WSRdbManagedConnectionImpl@23f823f8 執行方法 cleanup 時,
方法 cleanup 失敗。捕獲的異常:com.ibm.ws.exception.WsException: DSRA0080E: 
An exception was received by the Data Store Adapter. See original exception message: 
 Cannot call 'cleanup' on a ManagedConnection while it is still in a transaction..

異常的來源,居然是連接的close方法。

爲什麼close會失敗

在WebSphere的資料上沒有找到相關的描述,但是我在ibatis的文檔上找到了相關的描述(ibatis developer guide的12-13頁):

The element also allows an optional attribute commitRequired that can be true or
false. Normally iBATIS will not commit transactions unless an insert, update, or delete operation has been
performed. This is true even if you explicitly call the commitTransaction() method. This behavior
creates problems in some cases. If you want iBATIS to always commit transactions, even if no insert,
update, or delete operation has been performed, then set the value of the commitRequired attribute to true.
Examples of where this attribute is useful include:

  1. If you call a stored procedures that updates data as well as returning rows. In that case you would
    call the procedure with the queryForList() operation – so iBATIS would not normally commit the
    transaction. But then the updates would be rolled back.

  2. In a WebSphere environment when you are using connection pooling and you use the JNDI
    and the JDBC or JTA transaction manager. WebSphere requires all transactions on
    pooled connections to be committed or the connection will not be returned to the pool.

Note that the commitRequired attribute has no effect when using the EXTERNAL transaction manager.

結論及對策

從上面的描述上看到,WebSphere環境的連接是需要提交事務的,否則會被意外關閉。
並且,如果選擇ibatis的事務管理機制,就應該設置commitRequired屬性,要麼就應該使用spring的事務解決方案。

我們嘗試給查詢語句增加commit操作,果然異常信息不再出現,並且數據庫連接數也大幅度減少了。
看來,在生產系統中還是應該優先考慮成熟的解決方案,不要隨便造輪子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章