JPA各種ソリッドロックモードの違い
5528 ワード
JPA各種ソリッドロックモードの違い
文字数2084
読書143
コメント0
好きです
テキストアドレス
エンティティへのアクセスを同期させるために、JPAは2つのロックメカニズムを提供しています.この2つのメカニズムは、2つのトランザクションのうちの1つを回避し、知らないうちに別のトランザクションのデータを上書きすることができます.
エンティティ・ロックを使用すると、通常、2つのパラレル・トランザクションで次のような状況が発生しないようにします.
Adamのトランザクション読み出しデータX Barbaraのトランザクション読み出しデータX Adamのトランザクションは、データXを変更し、XA に変更します.
Adamのトランザクション書込みデータXA Barbaraのトランザクションは、データXを変更し、XB に変更します.
Barbaraのトランザクション書込みデータXB その結果、Adamの修正は完全にBarbaraに覆われたが、Barbaraはそれを知らなかった.このような場合は通常「汚れ読み」と呼ばれます.明らかに,我々が望んでいる結果はAdamがXAに書き込むことであり,BarbaraはXBに書き込む前にXAの修正を確認する必要がある.
楽観的ロックの動作原理
楽観的なロックは、実際に衝突が少ないという仮定に基づいており、発生しても、エラーを投げ出すのは、それらを避けるよりも受け入れやすく、簡単です.楽観ロックでは、1つのトランザクションが正しく完了することを許可しますが、別のトランザクションは例外を投げ出してロールバックし、再実行または破棄する必要があります.
また、AdamとBarbaraを例に挙げると、楽観的なロックを使用して発生する可能性があります.
Adamのトランザクション読み出しデータX Barbaraのトランザクション読み出しデータX Adamのトランザクションは、データXを変更し、XA に変更します.
Adamのトランザクション書込みデータXA Barbaraのトランザクションは、データXを変更し、XB に変更します.
BarbaraのトランザクションはデータXBに書き込もうとしたが、エラーが受信された.
Barbaraは、データXAの読み取り(または新しいトランザクションの再開)が必要です.
Barbaraのトランザクションは、データXAを変更し、XAB に変更します.
Barbaraのトランザクション書込みデータXAB ご覧のように、BarbaraはAdamの変更を確認するように強制され、Adamの結果を変更し続けて保存(修正をマージ)することができます.最後のデータには、AdamとBarbaraの変更が同時に含まれます.
楽観的なロックは完全にJPAによって制御されています.DBテーブルにバージョン番号列を追加保存する必要があります.リレーショナルデータを格納するための最下位のDBエンジンに完全に依存して動作します.
悲観ロックの動作原理
一部の人にとって、悲観的なロックは受け入れやすい.トランザクションが他のトランザクションによって同時に変更される可能性のあるエンティティを変更する必要がある場合、トランザクションはエンティティをロックするコマンドを開始します.すべてのロックは、トランザクションが終了するまで自動的に解放されます.
悲観的なロックを使用する場合は、次のようになります.
Adamのトランザクション読み出しデータX AdamのトランザクションロックX BarbaraのトランザクションはデータXの読み取りを望んでいるが、Xがロックされているため、を待つしかない.
Adamのトランザクションは、データXを変更し、XA に変更します.
Adamのトランザクション書込みデータXA Barbaraのトランザクション読み出しデータXA Barbaraのトランザクションは、データXAを変更し、XAB に変更します.
Barbaraのトランザクション書込みデータXAB ご覧のように、Barbaraは再びXABに強制的に書き込まれ、Adamの修正も含まれています.しかし、このスキームは楽観的なロックとはまったく異なり、BarbaraはAdamのトランザクションが完了してからデータを読み取る必要があります.さらに、シーンを正しく動作させるには、両方のトランザクションで手動でlockコマンドを開始する必要があります.(トランザクションが先に実行されるかどうかは不明なので、両方のトランザクションはデータを変更する前にロックする必要があります)楽観的なロックは、悲観的なロックよりもエンティティごとにバージョン列を追加しますが、その後、トランザクションでロック操作を開始する必要はありません.JPAはすべての検査を自動的に完了し、可能な異常を処理するだけです.
悲観的なロックは、下位データベースが提供するロックメカニズムを使用して、テーブル内の既存のレコードをロックします.JPAは、これらのロックをトリガーする方法を知り、一部のデータベースを完全にサポートすることはできません.
JPA仕様でもPESSIMISTICを提供する必要はありません.READ(多くのDBはWRITEロックのみをサポートしているため):
JPA実装は、
JPAで使用可能なロックタイプ
まず、エンティティに@Version注記が追加された列がある場合、JPAはエンティティに楽観的なロックを自動的に使用します.ロックコマンドを使用する必要はありません.ただし、いつでも次のタイプのロックを開始できます.これがデフォルトのロックタイプです.ObjectDBが言うように一般的に無視されるロックタイプでもあります.私の印象では、最後のロックがOPTIMISTICであることをよく知っていても、ロックタイプを動的に取得して渡す必要がある場合にのみ使用されます.この例は適切ではありませんが、デフォルト値でもオプションを提供する良いAPI設計です. 例:Java というオプションはあまり使われません.ただし、現在のエンティティへの参照をロックするには、別のエンティティを使用する必要があります.すなわち、現在のエンティティが変更されていなくても、他のエンティティは現在のエンティティが変更されているため、現在のエンティティへの参照をロックすることができます. 例: は、2つのエンティティ「本(Book)」と「本棚(Shelf)」があると仮定します.本を本棚に追加することができますが、本は本棚への引用を持っていません.1冊の本が2つの本棚に置かれないように、他の本棚に移動するすべての動作に鍵をかける必要があります.この動作をロックするためには、現在の本棚の本体をロックするだけでは十分ではありません.本はまだある本棚に置いていないかもしれません.すべての本棚をロックするのも合理的ではありません.彼らは異なる事務の中で異なるかもしれません.唯一合理的なのは、本の実体自体をロックすることであり、私たちの例では変化していないとしても(本棚の参照を持っていないため).
このモードは
これは
これはもう一つの少ないロックモードです.しかし、 トランザクションAは、楽観的ロックを使用してエンティティE を読み取る.トランザクションB要求エンティティE上のWRITEロック トランザクションBは、E上のロック をコミットして解放する.トランザクションAはEを更新し、 をコミットする.
ステップ4において、トランザクションBがバージョン列の値を増加しない場合、トランザクションAがBの変更を上書きすることは阻止できない.トランザクションBが悲観的ロックを使用している場合でも、ロックモード
JPAは、指定されたタイプのロックを開始するために、次の方法を提供します.
いくつかの find(Class entityClass, Object primaryKey, LockModeType lockMode) lock(Object entity, LockModeType lockMode) および他のDBからデータを取得する方法、例えば .
JPAのQueryインタフェースは、クエリによって取得されたすべてのエンティティをロックするsetLockMode(LockModeType lockMode)メソッドも提供する.
JPAの2つのロックメカニズムのいずれかを使用することができます.必要に応じて、悲観的なロックタイプ
詳細については、Vlad Mihalceaを参照してください.の素晴らしいブログです.
ようこそ(微信は「原文を読む」をクリックしてください)、微信の公衆アカウント「重度の高所恐怖症」にも注目してください.素晴らしい技術文章はここにあります.
文字数2084
読書143
コメント0
好きです
テキストアドレス
エンティティへのアクセスを同期させるために、JPAは2つのロックメカニズムを提供しています.この2つのメカニズムは、2つのトランザクションのうちの1つを回避し、知らないうちに別のトランザクションのデータを上書きすることができます.
エンティティ・ロックを使用すると、通常、2つのパラレル・トランザクションで次のような状況が発生しないようにします.
Adamのトランザクション読み出しデータX Barbaraのトランザクション読み出しデータX Adamのトランザクションは、データXを変更し、XA に変更します.
Adamのトランザクション書込みデータXA Barbaraのトランザクションは、データXを変更し、XB に変更します.
Barbaraのトランザクション書込みデータXB その結果、Adamの修正は完全にBarbaraに覆われたが、Barbaraはそれを知らなかった.このような場合は通常「汚れ読み」と呼ばれます.明らかに,我々が望んでいる結果はAdamがXAに書き込むことであり,BarbaraはXBに書き込む前にXAの修正を確認する必要がある.
楽観的ロックの動作原理
楽観的なロックは、実際に衝突が少ないという仮定に基づいており、発生しても、エラーを投げ出すのは、それらを避けるよりも受け入れやすく、簡単です.楽観ロックでは、1つのトランザクションが正しく完了することを許可しますが、別のトランザクションは例外を投げ出してロールバックし、再実行または破棄する必要があります.
また、AdamとBarbaraを例に挙げると、楽観的なロックを使用して発生する可能性があります.
Adamのトランザクション読み出しデータX Barbaraのトランザクション読み出しデータX Adamのトランザクションは、データXを変更し、XA に変更します.
Adamのトランザクション書込みデータXA Barbaraのトランザクションは、データXを変更し、XB に変更します.
BarbaraのトランザクションはデータXBに書き込もうとしたが、エラーが受信された.
Barbaraは、データXAの読み取り(または新しいトランザクションの再開)が必要です.
Barbaraのトランザクションは、データXAを変更し、XAB に変更します.
Barbaraのトランザクション書込みデータXAB ご覧のように、BarbaraはAdamの変更を確認するように強制され、Adamの結果を変更し続けて保存(修正をマージ)することができます.最後のデータには、AdamとBarbaraの変更が同時に含まれます.
楽観的なロックは完全にJPAによって制御されています.DBテーブルにバージョン番号列を追加保存する必要があります.リレーショナルデータを格納するための最下位のDBエンジンに完全に依存して動作します.
悲観ロックの動作原理
一部の人にとって、悲観的なロックは受け入れやすい.トランザクションが他のトランザクションによって同時に変更される可能性のあるエンティティを変更する必要がある場合、トランザクションはエンティティをロックするコマンドを開始します.すべてのロックは、トランザクションが終了するまで自動的に解放されます.
悲観的なロックを使用する場合は、次のようになります.
Adamのトランザクション読み出しデータX AdamのトランザクションロックX BarbaraのトランザクションはデータXの読み取りを望んでいるが、Xがロックされているため、を待つしかない.
Adamのトランザクションは、データXを変更し、XA に変更します.
Adamのトランザクション書込みデータXA Barbaraのトランザクション読み出しデータXA Barbaraのトランザクションは、データXAを変更し、XAB に変更します.
Barbaraのトランザクション書込みデータXAB ご覧のように、Barbaraは再びXABに強制的に書き込まれ、Adamの修正も含まれています.しかし、このスキームは楽観的なロックとはまったく異なり、BarbaraはAdamのトランザクションが完了してからデータを読み取る必要があります.さらに、シーンを正しく動作させるには、両方のトランザクションで手動でlockコマンドを開始する必要があります.(トランザクションが先に実行されるかどうかは不明なので、両方のトランザクションはデータを変更する前にロックする必要があります)楽観的なロックは、悲観的なロックよりもエンティティごとにバージョン列を追加しますが、その後、トランザクションでロック操作を開始する必要はありません.JPAはすべての検査を自動的に完了し、可能な異常を処理するだけです.
悲観的なロックは、下位データベースが提供するロックメカニズムを使用して、テーブル内の既存のレコードをロックします.JPAは、これらのロックをトリガーする方法を知り、一部のデータベースを完全にサポートすることはできません.
JPA仕様でもPESSIMISTICを提供する必要はありません.READ(多くのDBはWRITEロックのみをサポートしているため):
JPA実装は、
LockModeType.PESSIMISTIC_WRITE
の代わりにLockModeType.PESSIMISTIC_READ
を使用することを可能にするが、逆は不可能である.JPAで使用可能なロックタイプ
まず、エンティティに@Version注記が追加された列がある場合、JPAはエンティティに楽観的なロックを自動的に使用します.ロックコマンドを使用する必要はありません.ただし、いつでも次のタイプのロックを開始できます.
LockModeType.Optimistic
LockModeType lockMode = resolveLockMode();
A a = em.find(A.class, 1, lockMode);
LockModeType.OPTIMISTIC_FORCE_INCREMENT
LockModeType.PESSIMISTIC_READ
LockModeType.PESSIMISTIC_WRITE
と似ていますが、トランザクションがエンティティに書き込みロックをかけていない場合、エンティティの読み取りをブロックすることはできません.また、LockModeType.PESSIMISTIC_READ
を使用して他のトランザクションをロックすることもできます.WRITEロックとREADロックの違いは,この2つの文章(here(ObjectDB)とhere(OpenJPA))によって詳細に説明されている.しかしながら、仕様において許容されるだけでなく、多くのインプリメンテーションも別々に処理されていないため、このロックモードはしばしばLockModeType.PESSIMISTIC_WRITE
に等価である.LockModeType.PESSIMISTIC_WRITE
LockModeType.PESSIMISTIC_READ
の拡張版です.WRITE
ロックが発生すると、JPAはデータベースの助けを得て、READ
ロックのように書き込みのみを禁止するのではなく、他のトランザクションがエンティティを読み取ることを阻止します.LockModeType.PESSIMISTIC_FORCE_INCREMENT
PESSIMISTIC
とOPTIMISTIC
を組み合わせたときに使用することができる.次のシーンでは、PESSIMISTIC_WRITE
を単独で使用するのは無効です.LockModeType.PESSIMISTIC_FORCE_INCREMENT
は、トランザクションBにバージョン番号の更新を強制し、トランザクションAを失敗させ、OptimisticLockException
を投げ出す.JPAは、指定されたタイプのロックを開始するために、次の方法を提供します.
いくつかの
EntityManager
メソッドは、例えば、ロックタイプを指定するオプションのパラメータを受信する.merge()
またはrefresh()
JPAのQueryインタフェースは、クエリによって取得されたすべてのエンティティをロックするsetLockMode(LockModeType lockMode)メソッドも提供する.
JPAの2つのロックメカニズムのいずれかを使用することができます.必要に応じて、悲観的なロックタイプ
PESSIMISTIC_FORCE_INCREMENT
を選択して、両者を混ぜて使用することもできます.詳細については、Vlad Mihalceaを参照してください.の素晴らしいブログです.
ようこそ(微信は「原文を読む」をクリックしてください)、微信の公衆アカウント「重度の高所恐怖症」にも注目してください.素晴らしい技術文章はここにあります.