環境:JTA嵌套事務鎖
我們有部署在一個JBoss 4.2.3.GA服務器和其使用Hibernate 3.4和1.0 JTA的應用程序。
有一個進口商創建或更新某些實體,然後導入一些數據。大多數導入是在一個新的事務中完成的,原因有很多,在每個事務中,在外部事務中創建/更新的實體可能會再次更新。
調用順序是這樣的僞代碼:
服務1:
//container managed transaction T1 is started here
import() {
A a = ... ;//new or read from database
if(isNew(a)) {
create(a);
} else {
update(a);
}
Service1 s = ...; //injected or looked up
for(D d : someDataList) {
//nested transaction T2 is started due to this call, T1 should be suspended
s1.importData(d);
//nested transaction T2 should have been committed here
}
客服2:
@TransactionAttribute(REQUIRES_NEW)
importData(D d) {
A a = ...; //get the corresponding A instance and update as needed
update(a);
//other stuff such as importing d
}
問題:
現在的問題是,我們」 d最終遇到了賽車狀況wi數次交易試圖鎖定相同的表格,但目前爲止我們還沒有能夠重現問題,也沒有找出真正的原因。
我們有一些假設,但:
由於T1期間,一些實體被更新時,TRANSATION獲得了某種數據庫鎖。然後T1被暫停,因爲T2啓動,而T2又試圖獲取相同的數據庫鎖並因此被阻止。 T2最終超時,然後T1可以正常完成並釋放鎖。
可能的解決方法?:
到目前爲止,只有似乎是一個可能的解決方案:在包裝T1的所有更新到另一個事務T1 *(可能完全跳過T1),並有T1 *和T2運行順序。
這是一個理智的解決方案,前提是業務案例允許這樣做(我不確定,因爲我自己沒有實現該業務案例)?
也可能有其他解決方案,如果是這樣,請提供一些提示。然而,我懷疑這是因爲在T2嘗試獲取它之前T1似乎不得不釋放鎖,從而基本上使T1和T2順序運行。
問題
從上面,下面的問題出現:
- 是我們的假設是正確的,即不T1保持的鎖T2需要以及和它無法釋放,因爲它被暫停?
- 我上面描述的解決方案是唯一的方法,還是沒有手動事務劃分還有其他方法?
感謝您閱讀這一切:)
更新1:
因爲我不是我要鑽研它,以及代碼的作家。到目前爲止,在Hibernate中沒有任何顯式鎖定的提示,因此AFAIK Hibernate在寫入數據庫resp期間僅使用數據庫鎖。當數據庫連接打開時。
我們使用自動刷新,因此T1可能會在T2嘗試相同之前打開連接,但T1無法提交併關閉連接,因爲它在T2提交後纔會掛起。因此,在T2刷新之前,數據庫似乎因T1的刷新而導致的鎖定無法釋放。
使用手動刷新不會是一個解決方案,因爲如果T2在T1之前提交,但對實體的更改相反,我們會丟失更新。我知道這是在設計上的缺陷,我們需要解決這個問題,但我也想確認我們的假設,以提供一個合理的修復:)
你在哪裏獲得鎖? – Adi 2013-03-25 17:52:30