重複する質問:
/programming/129329/optimistic-vs-pessimistic-locking
上記のリンクから回答をコピー/貼り付け:
楽観的ロックは、レコードを読み取り、バージョン番号をメモし、レコードを書き戻す前にバージョンが変更されていないことを確認する戦略です。レコードを書き戻すときは、バージョンの更新をフィルタリングして、アトミックであることを確認します。(つまり、バージョンをチェックしてからレコードをディスクに書き込むまでの間に更新されていません)、1回のヒットでバージョンを更新します。
レコードがダーティ(つまり、バージョンが異なる)の場合、トランザクションを中止し、ユーザーはそれを再開できます。
この戦略は、セッションのためにデータベースへの接続を必ずしも維持する必要がない、大量システムおよび3層アーキテクチャーに最も適しています。この状況では、接続はプールから取得されるため、クライアントは実際にはデータベースロックを維持できず、アクセスごとに同じ接続を使用していない可能性があります。
悲観的ロックとは、レコードが完了するまで、レコードを排他的に使用するためにロックすることです。楽観的ロックよりも完全性がはるかに優れていますが、アプリケーションの設計でデッドロックを回避するように注意する必要があります。悲観的ロックを使用するには、データベースへの直接接続(通常、2層クライアントサーバーアプリケーションの場合)か、接続とは無関係に使用できる外部で利用可能なトランザクションIDが必要です。
後者の場合、TxIDでトランザクションを開き、そのIDを使用して再接続します。DBMSはロックを維持し、TxIDを介してセッションをバックアップすることができます。これは、2フェーズコミットプロトコル(XAやCOM +トランザクションなど)を使用した分散トランザクションが機能する方法です。
編集(パフォーマンスの問題に対処するための情報を追加):
パフォーマンスは、環境によって異なります。次の要素を考慮して決定します。
ほとんどの状況で並行性があるため、楽観的であることがわかります。ただし、RDBMSと環境によっては、パフォーマンスが低下する場合があります。通常、オプティミスティックロックを使用すると、値をどこかに行バージョン付けする必要があることがわかります。
たとえば、MS SQL Serverの場合、TempDBに移動し、列の最後に12〜14バイトの何かが追加されます。スナップショット分離などの分離レベルでオプティミスティックロックをオンにすると、断片化が発生する可能性があり、行の最後に追加のデータが含まれ、ページがいっぱいになり、ページ分割が発生する可能性があるため、Fill Factorを調整する必要があります。あなたのパフォーマンス。TempDBが最適化されていない場合、これはそれほど速くありません。
だから私はチェックリストは次のとおりだと思います:
- -行のバージョン管理の形式を処理するのに十分なIO /リソースがありますか?そうでない場合は、オーバーヘッドが追加されます。その場合、書き込みのために頻繁にデータをロックしている間にデータを頻繁に読み取ると、読み取りと書き込みの同時実行性が大幅に改善されます(書き込みは引き続き書き込みをブロックしますが、読み取りは書き込みをブロックしなくなります)。
- -あなたのコードはデッドロックの影響を受けやすいですか、それともロックが発生していますか?長いロックまたは多くのデッドロックが発生していない場合は、オプティミスティックロックの追加のオーバーヘッドによって処理が速くなることはありません。もちろん、ほとんどの場合、ここではミリ秒単位で話しています。
- -DBが大きい(または非常に限られたハードウェア上)で、データページがほぼいっぱいになっている場合、RDBMSによっては、主要なページ分割とデータの断片化が発生する可能性があるため、有効にした後でインデックスの再作成を検討してください。
それらは私の問題についての私の考えであり、コミュニティからのより多くの意見を聞くことを受け入れます。