簡體   English   中英

事務隔離級別

[英]Transaction Isolation Level

我將嘗試在 JPA 事務隔離級別中描述我的問題。

數據庫結構:

  • Table1 1 -> PK 定義為日期('ddMMyyyy')
  • Table2 -> 使用 FK 到表 1

JPA(隔離級別:: read_commited )-代碼:

    Query query = em.createQuery("from Table1 trd where trd.id = :d");
    query.setParameter("d", date);

    Table1 t = null;
    try{
        t = (Table1) query.getSingleResult();
    }catch(javax.persistence.NoResultException e){
        t = null;
    }

    if(t==null){
        t=new Table1 (date);
        em.persist(trd);
    }

    for(Table2 q:tables2){
        q.setTable1(t);
        em.merge(q);
    }

所以程序檢查記錄是否存在於數據庫中,如果不存在則創建新記錄。 如果系統僅基於一個線程,則方法是完全正確的。 否則可能會出現這樣的情況:

  • 線程1:檢查數據庫中是否存在按日期表示的實體
  • 線程2:做完全一樣

他們都認為這樣的記錄還沒有,所以添加一個新的。 在提交交易之前一切正常。 第一個將毫無例外地提交,購買第二個與主鍵重復相關的異常。

除了將隔離級別更改為SERIALIZABLE之外,是否有可能保留這種情況?

是的,一般隔離級別 = SERIALIZABLE 應該可以解決您的問題。 將隔離級別更改為最嚴格的選項時,不要低估副作用。 它可能會影響數據庫利用率以及請求吞吐量。 也許您可以在創建 T1 后顯式提交您的 TRX,然后打開另一個 TRX:EntityManager.getTransaction().commit()

您仍然必須捕獲重復鍵異常。

這是高度並發環境中數據庫最難解決的問題之一。 最后,您唯一真正的解決方案是捕獲異常並適當地處理它。

根據您提供的代碼,很難判斷這可能是什么。 如果這是一個 web 應用程序,您很可能希望捕獲重復鍵異常並向最終用戶顯示一些有用的消息。 例如“此記錄已創建”,或類似的內容。

暫無
暫無

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

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