web-dev-qa-db-ja.com

楽観的ロックが悲観的ロックよりも速いのはなぜですか?

どちらの形式のロックでも、現在別のプロセスで使用されている場合、プロセスはレコードの正しいコピーを待機します。悲観的ロックでは、ロックメカニズムはDB自体(ネイティブロックオブジェクト)から取得されますが、楽観的ロックでは、ロックメカニズムは、レコードが「古く」なっていないかどうかを確認するタイムスタンプのような行バージョン管理の一種です。

しかし、どちらも2番目のプロセスをハングさせます。だから私は尋ねます:なぜ楽観的ロックは一般的に悲観的ロックよりも速く/優れていると考えられていますか?また、楽観よりも悲観が優先されるユースケースはありますか?前もって感謝します!

9
Mara

重複する質問:

https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking

上記のリンクから回答をコピー/貼り付け:

楽観的ロックは、レコードを読み取り、バージョン番号をメモし、レコードを書き戻す前にバージョンが変更されていないことを確認する戦略です。レコードを書き戻すときは、バージョンの更新をフィルタリングして、アトミックであることを確認します。 (つまり、バージョンを確認してからレコードをディスクに書き込むまでの間に更新されていません)、1回のヒットでバージョンを更新します。

レコードがダーティである(つまり、バージョンが異なる)場合、トランザクションを中止し、ユーザーはそれを再開できます。

この戦略は、セッションのためにデータベースへの接続を必ずしも維持する必要がない、大量システムおよび3層アーキテクチャーに最も適しています。この状況では、接続はプールから取得されるため、クライアントは実際にはデータベースロックを維持できず、アクセスごとに同じ接続を使用していない可能性があります。

悲観的ロックとは、レコードが完了するまで、レコードを排他的に使用するためにロックすることです。楽観的ロックよりも完全性がはるかに優れていますが、デッドロックを回避するためにアプリケーション設計に注意する必要があります。悲観的ロックを使用するには、データベースへの直接接続(通常は2層クライアントサーバーアプリケーションの場合)か、接続とは無関係に使用できる外部で利用可能なトランザクションIDが必要です。

後者の場合、TxIDでトランザクションを開き、そのIDを使用して再接続します。 DBMSはロックを維持し、TxIDを通じてセッションをバックアップすることができます。これは、2フェーズコミットプロトコル(XAやCOM +トランザクションなど)を使用した分散トランザクションが機能する方法です。

編集(パフォーマンスの問題に対処するための情報を追加):

パフォーマンスは、環境によって異なります。次の要素を考慮して決定します。

ほとんどの状況で並行性があるため、楽観的であることがわかります。ただし、RDBMSと環境によっては、パフォーマンスが低下または向上する場合があります。通常、オプティミスティックロックを使用すると、値をどこかに行バージョン付けする必要があることがわかります。

たとえば、MS SQL Serverでは、TempDBに移動され、列の最後に12〜14バイトのものが追加されます。スナップショット分離などの分離レベルでオプティミスティックロックをオンにすると、断片化が発生する可能性があり、行の最後に追加のデータが含まれ、ページがいっぱいになり、ページ分割が発生する可能性があるため、フィルファクターを調整する必要があります。あなたのパフォーマンス。 TempDBが最適化されていない場合、これはそれほど速くありません。

だからチェックリストは:

  • -行のバージョン管理の形式を処理するのに十分なIO /リソースがありますか?そうでない場合は、オーバーヘッドが追加されます。その場合、書き込みのために頻繁にデータをロックしている間にデータを頻繁に読み取ると、読み取りと書き込みの同時実行性が大幅に改善されます(書き込みは引き続き書き込みをブロックしますが、読み取りは書き込みをブロックしなくなります)。
  • -あなたのコードはデッドロックの影響を受けやすいですか、それともロックが発生しますか?長いロックや多くのデッドロックが発生していない場合は、オプティミスティックロックの追加のオーバーヘッドによって処理が速くなることはありません。もちろん、ほとんどの場合、ここではミリ秒と呼んでいます。
  • -DBが大きい(または非常に限られたハードウェア上)で、データページがほぼいっぱいになっている場合、RDBMSによっては、主要なページ分割とデータの断片化が発生する可能性があるため、有効にした後でインデックスの再作成を検討してください。

それらは、この問題についての私の考えであり、コミュニティからのより多くの意見を受け入れることができます。

8
Ali Razeghi

あなたは楽観的ロックを誤解しています。

楽観的ロックでは、トランザクションが互いに待機することはありません。

楽観的ロックはトランザクションを失敗させる可能性がありますが、「ロック」が行われていなくても失敗します。また、楽観的ロックが原因でトランザクションが失敗した場合、ユーザーは最初からやり直す必要があります。 「楽観的」という言葉は、まさにこの理由でトランザクションが失敗する原因となる状態が非常に例外的にしか発生しないという期待からきています。 「楽観的」ロックとは、「実際にはロックが必要ないことを願って、実際のロックを取得しないことです。それが間違っていることが判明した場合は、避けられない失敗を受け入れます。」というアプローチです。

11
Erwin Smout

データベースの観点からは実際にはロックがないため、楽観的ロックは一般に高速です。バージョン列(またはora_rowscnのような疑似列)を尊重するかどうかは、アプリケーション次第です。通常、多くのアプリケーションが同じデータベースに接続されているため、dbは共有リソースになり、ハングすると、すべてのクライアントが影響を受けます。

楽観的ロック戦略では、「ハング」はクライアント側で発生し、他には影響しません。

ただし、レコードが頻繁に更新されると、楽観的ロックの場合にレコードを何度も再読み取りしてしまい、楽観的戦略のほとんどの利点を失う可能性があります。

私はどちらのアプローチの優位性についても同意しません。どちらも誤用される可能性があります。ペシミスティックは、より危険であるという理由だけでエラーが発生しやすくなります。ロックはデータベースレベルで発生し、RDMSによってはロック対象を制御できない場合があります(ロックのエスカレーション)。ロックの順序を手動で処理する必要があります。

1
a1ex07

Optimisticロックは、並行トランザクションが互いに影響を与えることなく完了することができると想定しています。したがって、トランザクションの実行中に強制されるロックがないため、楽観的ロックの方が高速です。これは、同時実行の問題が発生しないようにするための対策ではありません。トランザクションは、他のトランザクションがデータを変更していないことを確認するだけです(データセット、タイムスタンプデータタイプ、古い値と新しい値をチェックする3つの方法)。変更の場合、トランザクションはロールバックされます。

Pessimisticロックは、同時トランザクションが相互に競合することを想定しているため、ロックが必要であり、ISOLATIONレベル(Read Uncommitted、Read Committed、Repeatable)を指定することで行われます読み取りおよび直列化可能)トランザクション管理。ロックを取得することにより、同時実行性の問題を解決します。ロックは、共有リソースまたはオブジェクト(テーブル、データ行、データブロック、キャッシュされたアイテム、接続、およびシステム全体)を保護するのに役立ちます。ロックには、共有ロック、更新ロック、挿入ロック、排他ロック、トランザクションロック、DMLロック、スキーマロック、バックアップ/リカバリロックなど、さまざまな種類があります。

より多くのアイデアを得るために

0
Premraj