Aggregateのトランザクションの管理


  • オーダーの場合、オペレータが出荷ステータスに変更された場合、ユーザーは配送先を変更できますか?
  • メモリキャッシュを使用しない場合、オペレータスレッドとクライアントスレッドは、同じ受注agreegerを表す他のオブジェクトを生成します.
  • オペレータスレッドとクライアントスレッドは概念的に同じであるが、物理的に異なるオブジェクトが使用される.
  • のため、オペレータスレッドが受注アグリガーオブジェクトを出荷状態に変更しても、顧客スレッドが使用する受注アグリガーオブジェクトには影響しません.お客様のトピックでは、受注アグリガーオブジェクトは配送オブジェクトの前にあるため、配送情報を変更できます.
  • この場合、2つのスレッドは、既存の配送情報を使用して配送状態に変更することができ、その間、顧客は配送情報を変更することができ、agreegateの一貫性を破壊する可能性がある.
  • アグリグットの一貫性を保証するには、次の2つの点の1つを行う必要があります.
  • 事業者は、配送情報の表示およびステータスの変更中に、お客様がagrigatを変更することを防止します.
  • 事業者が配送情報を照会した後、顧客が情報を変更した場合、事業者はアグリガーを再照会し、変更します.
  • 両者はアグリグット自身の傾向と関係がある.DBMSがサポートするトランザクションに加えて、agrigatに追加のトランザクション処理テクニックを提供する必要があります.
  • パッシブロック
  • 非線形ロック
  • Pessimistic Lock

  • プリエンプトロック(Persimisic Lock)は、agrigatの使用が終了する前に他のスレッドを変更することを防止する方法である.
  • スレッド1がプリエンプトロック方式でagrigatを取得すると、agrigatに対するロックが解除されるまでスレッド2はブロックされる.
  • スレッド1がagrigatを変更してトランザクションをコミットした場合、ロックは解除されます.この瞬間、待機していたスレッド2はアグリゲットに近づく.
  • スレッド2がアグリゲートを救うと、スレッド1が修正したアグリゲートの内容が表示されます.
  • あるスレッドは、アグリガーを精査および修正する際に、他のスレッドが修正できないため、アグリガーを同時に修正する際に発生するデータ競合の問題を解消します.
  • オペレータスレッドが最初にプリエンプトロックで受注エージェントを要求すると、オペレータスレッドがロック解除される前にクライアントスレッドは待機状態となり、ロック解除時にクライアントスレッドが要求する受注エージェントは、オペレータスレッドが修正された配送状態の受注エージェントとなる.
  • 配送状態のため、注文アグリガーは配送先の変更中にエラーが発生し、取引に失敗した.(出荷開始済み、出荷先住所変更不可)
  • プリエンプトロックは、通常、DBMSによって提供される行単位ロックを使用して実現される.
  • oracleを含む複数のDBMSは、for updateと同様のクエリを使用して、1人のユーザのみが特定のレコードにアクセスできるロックデバイスを提供する.
  • JPAのEntity Managerは、LockModeTypeをパラメータとするfind()メソッドを提供しています.
    public abstract <T> T find(   
    	Class<T> aClass,
      Object o,
      javax.persistence.LockModeType lockModeType 
    )
    // Maven: org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final (hibernate-jpa-2.1-api-1.0.0.Final.jar)
    転送値が
  • 2LockModeType.PESSIMISTIC_WRITEの場合、プリエンプトロック方式は、エンティティにマッピングされたテーブルを使用して適用され得る.
  • LockModeType

  • JPA ProviderとDBMSによって異なるロックモードが実現され、HypernetではPESSIMISTIC_WRITEロックモードが使用され、for updateクエリが使用されてハッシュプリエンプトロックが実現される.
  • プリエンプトロックと膠着状態

  • プリエンプトロック機能を使用する場合は、ロック順にデッドロックが発生しないように注意してください.
    たとえば、2つのスレッドがロックを試みた場合:
    1. 스레드1: A 애그리거트에 대한 선점 잠금 구함
     2. 스레드2: B 애그리거트에 대한 선점 잠금 구함
     3. 스레드1: B 애그리거트에 대한 선점 잠금 시도
     4. 스레드2: A 애그리거트에 대한 선점 잠금 시도
  • の順序では、スレッド1はBアグリガーに対するプリエンプトロックを永遠に得ることができない.スレッド2はB計画に対するロックをプリエンプトしているからです.
  • と同じ理由で、スレッド2はA agrigateをロックできません.◇スレッド2はすでにA計画に対するロックを奪っている.
  • の2つのスレッドは、相手スレッドが最初にプリエンプトしたロックを取得できないため、次のステップを行うことができず、スレッド1とスレッド2は硬直状態に陥ります.
  • プリエンプトロックによる硬直状態は、ユーザ数が多い場合に発生する可能性が高く、ユーザ数が多い場合には、硬直状態のスレッドがより速く増加する.
  • より多くのスレッドが硬直するにつれて、システムは徐々に何でもできる状態に達するだろう.
  • このような問題を回避するには、ロックを求めるときに최대 대기 시간を指定します.JPAがプリエンプトをロックしようとしたときの最大待ち時間を指定するには、次のヒントを使用します.
  • JPAのjavax.persistence.lock.timeoutプロンプトは、ロック待ち時間をミリ秒単位で指定します.指定した時間内にロックが見つからないと異常が発生します.
    public abstract <T> T find(   
    	Class<T> aClass,
      Object o,
      javax.persistence.LockModeType lockModeType,
      java.util.Map<String, Object> map 
    )
    // Maven: org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final (hibernate-jpa-2.1-api-1.0.0.Final.jar)
  • プロンプトを使用するときに注意したいのは、DBMSによってプロンプトが適用されないことです.プロンプトを使用する場合は、使用中のDBMSが関連機能をサポートしていることを確認してください.(JPAがDBMSのヒステリシス時間をどのように処理するかを確保する)
  • .
  • DBMSによると、
  • クエリーで指定できる待機時間、
  • DBMSもあり、
  • インタフェース単位でしかヒステリシス時間を指定できません.