2017-01-19 3 views
3

更新しようとしているオブジェクトのDBレベル・ロックとの同時性を保証したいWebアプリケーションがあります。バッチ変更や他のユーザーやプロセスがDBに矛盾をもたらすことがないようにしたいと思います。隔離レベルとJPAのオプティミスティック・ロック・ハイバネーション

は私が分離レベルは、一貫性のある状態で書き込まれたデータを確保することができます読んで一貫性と@Versionフィールドと楽観的ロックを確保することを参照してください。

私の質問は、分離レベルとの整合性だけを保証できないのですか?レコードをシリアライズ可能(パフォーマンスを考慮しない)に更新する私のトランザクションを作成することによって、トランザクションとロックを更新または獲得しようとしている他のトランザクションによって適切なロックが取られることを保証しませんか? これにはバージョン管理かタイムスタンプ管理が本当に必要ですか?

答えて

1

すべてのトランザクションをシリアライズ可能にすると、小さな独立したWebアプリケーション(データベース上で動作するアプリケーションのみ)について言及していない限り、デザインには自信があります特定のデータベースに当てはまる唯一のアプリケーションではないかもしれないという事実。

決定けれどもSerializableの分離レベルの組み込み、または他の言葉で悲観的ロックは、非常によくする必要があります私の意見ではとのために適用される:数行しか更新

  • 大規模なデータベースと短いトランザクション
  • 2つの並行トランザクションが同じ行を変更する可能性は比較的低いです。
  • 比較的長時間実行されるトランザクションは、主に読み取り専用です。

私の経験によれば、オプティミスティックロックを使用するほとんどのケースでは、頻繁な同時変更がほとんどのケースで発生するため、最も有益な決定となります。 楽観的なロックは間違いなく他のアプリケーションの実行を速くするのにも役立ちます。

我々は悲観的取るときに - オプティミスティック・ロック戦略スペクトルを、私の意見では真実がここにある、シリアライズの風味とオプティミスティック・ロックに向けてどこかにもっとあります。その答えは、私は私のJPA証明書にpreapringたとき、多くの複雑なWebプロジェクトで、私のノートからの私の個人的な経験に基づいている

私は本当にここで何を参照することはできません。

希望に役立ちます。与えられたトランザクションがコミットまたはロールバックされるまで

+0

すぐにお返事ありがとうございます! これは、実際には、トランザクションを開始する前にISOLATION LEVEL(SERIALIZABLE)が実際に悲観的なロックを取得していることを意味しますか? 他の分離レベルについては特にREPEATABLE READについてはどうでしょうか。これも行レベルで悲観的なロックですか? – Dhruv

+0

JPAに関しては、APIをアンラップしてベンダー特有の構成とヒント(apiが時々サポートする)を使用しない限り、分離レベルを直接選択することはできません。ペシミスティックロックを取得すると、繰り返し不可能な読み取りとファントム読み取りを自動的に防止します。 –

+0

しかし、HibernateとSpringでは、トランザクションを開始する前にISOLATION Levelをプロパティとして設定することができます。したがって、これは内部的にトランザクションロックを取る必要があり、これは悲観的なロックでなければなりません。私の更新メソッドで、ISOLATIONレベルがSERIALIZABLEであると言うと、私のトランザクションが実際にロックを持っていれば、その間に他の更新はできないと保証されませんか? – Dhruv

2

あなたが選択した分離レベルに応じて、特定のリソースをロックしようとしている - それは、SQLのテーブル全体、行またはブロックにロックすることができます。それは悲観的なロックであり、トランザクションを実行するときにデータベースレベルで保証されます。一方

オプティミスティック・ロックは、複数のトランザクションがめったにないので、ロックが、このアプローチに必要とされない互いに干渉しないと仮定しています。これは、読み取りの間にレコードのバージョンが変更されたかどうかを確認するために、@Version属性を使用するアプリケーション側のチェックです。

ほとんどの操作が複数のHTTP要求にまたがるので、Webアプリケーションでは楽観的なロック方法を使用することが妥当です。通常、1つの要求でデータベースから情報を取り出し、別の情報で更新します。長いデータベースリソースをロックしてトランザクションを開いたままにすることは、非常に高価で賢明ではありません。そのため、私たちが作業しているデータセットを誰も使用しないことを前提としています。これは安価です。前提が間違っていて、他の人の要求の間にバージョンが変わった場合、Hibernateは行を更新せず、OptimisticLockingExceptionを投げます。開発者は、この状況を管理する責任があります。

単純な例です。オンラインオークションサービス - あなたはアイテムページを見ています。あなたはその記述と仕様を読む。すべてが、5分と言いましょう。悲観的なロックといくつかの分離レベルを使用すると、この特定のアイテムページ(またはすべてのアイテムも)から他のユーザーをブロックすることができます。楽観的なロックを使用すると、誰もがアクセスできます。あなたがそれに適切なボタンをクリックするようにそれに入札しようとしている項目について読んだ後。その間にこのアイテムを見て、その状態を変更した(所有者が説明を変更した他のユーザーが他の入札者に変更した)場合は、アプリケーションの入札を承認する前に、(アプリの実装に応じて)データベースに保存されているバージョンと同じではありません。

あなたのためにいくつかを明確にする希望。

+0

答えをありがとう。しかし、もう一度アイソレーションレベルは実際には悲観的なロックである?分離レベルがシリアライズされ、トランザクションが開始されるとどうなりますか?それらのうちの1つがブロックされるか、オプティミスティックロックの例外と同様の休止状態からの例外がいくつか期待できますか? – Dhruv

+0

はい、基本的に、トランザクションで未コミットの読み取りよりも高い分離レベルを使用すると、悲観的なロックが行われます。他の人がそれを必要としているかどうかにかかわらず、使用しているリソースにロックをかけます。シリアライズされた分離レベルでは、あなたが作業しているテーブル全体をロックし、他のトランザクションがアクセスするのを待たなければならない例外はありません。 –

+0

私が答えてくれた例のRESTアプリケーションを想像してみてください。 1つのユーザーがアイテムに入札できるように、シリアル化可能なアイソレーションを使用してアイテムのテーブル全体をロックするのは正しいでしょうか(他のユーザーアプリケーションはアイテムのビューを取得できません)。コードとトランザクションのトランザクションをユーザーの観点から区別する必要があります(通常、Webアプリケーションでは多くの要求を意味します)。会話を見て(http://what-when-how.com/hibernate/implementing-conversations-hibernate/)多分それは物事を明るくするでしょう。 –

関連する問題