簡體   English   中英

如何使用Java持久性重試鎖定等待超時?

[英]How to retry a lock wait timeout using java persistence?

我需要對使用Java持久性時重試“可重試”異常(例如類似鎖等待超時之類)的正確方法進行一些說明。 例如,使用偽代碼,例如:

EntityTransaction tx = em.getTransaction();
tx.begin();
for (a bunch of objects) {
  em.persist(object);
}
tx.commit();

如果數據庫中有鎖,有時會在em.persist調用中引發異常。 我可以將其包裝在try / catch中然后重試嗎(很明顯,有一些計數)? 還是我必須包裝整個tx.begin / commit並重

謝謝

假設沒有鎖定超時作為解決數據庫死鎖的方法,那么一個更簡單的解決方案是對請求使用更長的超時。 將超時設置為N * (C + 1)秒,而不是使用N秒的超時並重試最多C次。

(如果您將鎖定超時用作死鎖的一種解決方法,那么您會遇到更大的問題。您最好嘗試解決死鎖的根本原因,因為即使使用C重試,您的交易也有可能獲勝不能通過。)

只要EntityManager拋出的異常不會將事務標記為僅回滾(LockTimeoutException是此類示例之一,而PessimisticLockException並非如此),則可以繼續處理當前事務中的事務。

如果TX僅被標記為回滾,則您必須對TX進行保釋,然后重試TX內發生錯誤之前的任何嘗試,然后繼續操作。

如果要通過JPA循環進行工作,那么您很有可能是DELETE或UPDATE jpql查詢的候選人。

如果您按照規范進行編程,則實際上應該處置整個EntityManager並重新開始。 沒有任何例外可以保證在EM級別“可重試”。 如果persist()方法產生異常,則整個持久性會話將被視為不一致/不確定。

有時它將起作用。 我知道在休眠狀態下,您通常可以在樂觀鎖定異常之后嘗試獲得收益。 但是總的來說,如果您試圖捕獲並從entitymanager異常中恢復並保持相同的entitymanager,則您將依賴於供應商特定的行為,這些行為可能定義不清。

更多信息在這里。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM