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


9

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

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


5
ネーミングには非常に短い説明があります。オプティミスティックロックは、競合するロックの可能性が低い場合にうまく機能します。複数のプロセスの相互作用については楽観的です。悲観的ロックは、競合するロックの可能性が高い場合にうまく機能します。複数のプロセスの相互作用については悲観的です。どちらも、反対のほうが適切な場合に最適とは言えません。
Mark Storey-Smith

楽観的ロックは、ワークロードに応じて、悲観的ロックよりも速い場合とそうでない場合があります。
AK

回答:


8

重複する質問:

/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によっては、主要なページ分割とデータの断片化が発生する可能性があるため、有効にした後でインデックスの再作成を検討してください。

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


ありがとう@Ali Razeghi(+1)-この質問にはdba.seがより適切だと思います。また、これはすばらしい答えですが、パフォーマンスに関する私の質問には答えません(一方が他方より速い場合)。再度、感謝します!
Mara

こんにちはマーラ、それは良い点です。答えを広げました。ありがとう。
Ali Razeghi 2013年

11

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

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

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


1

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

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

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

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


興味深い点a1ex07、書き込みは常に他の書き込みをブロックするため、オプティミスティックロックにはロックが含まれますが、正しいですか?
Ali Razeghi 2013年

いいえ、ありません。それが「より速い」理由です。
Erwin Smout 2013年

これはOracleの場合にも当てはまりますが、MS SQL Serverの場合、デフォルトで「コミットされた読み取り」分離レベルを使用するため、オプティミスティックロックを使用すると、読み取りスレッドと書き込みスレッドを同時に機能させることができますが、書き込みは、ブロッキングスレッドがコミットするまで書き込みをブロックします。
Ali Razeghi

@Ali Razeghi:私はあなたの主張に従っているのかわかりません。読み取りがコミットされたSQLServerでは、 `READ_COMMITTED_SNAPSHOT`がオンになっていない限り、ライターはデフォルトでリーダーをブロックします。オプティミスティックロックは、dbリソース(行/ページ/テーブル)に対するロックではなく、バージョンが予想と一致しない場合にデータベースを使用してレコードを更新しないすべてのアプリケーション間の何らかの合意です。
a1ex07 2013年

1
@Eamon Nerbonne:私は「ライターはリーダーをブロックしない」と言いました...「ライターをブロックする/ライターをブロックしない」について何か言及したのはどこですか?
a1ex07 2013年

0

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

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

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


-3

悲観的ロックの方が楽観的ではなく遅いと言ったり、楽観的の方が速いと言うのは誤りです。この不適切な考え方を示す古典的なクエリの1つは、次のように、さまざまなRDBMSで集計を行うことです。

SELECT COUNT(*) FROM atable

ネイティブオプティミスティックアプローチをサポートするRDBMSでは、このクエリにかかる時間は、ネイティブペシミスティックロックを持つ人よりもはるかに重要です。

たとえば、私のPCでは、同じクエリにSQL Serverで27ミリ秒、PostGreSQLで109ミリ秒かかります...

MVCC行の無効なバージョンを読み取るために必要な追加のオーバーヘッドと、集計でゴーストレコードをカウントしないと、悲観論にはない余分なコストが追加されます。


4
DBMSの同時実行制御アプローチは、楽観的/悲観的ロックと直交しており、2つの異なるDBMSでクエリの実行時間を比較すると誤解を招きます。
Mustaccio 2017年

SQL Serverは2つのロックモードを実行できるため、ユーザーの同時実行アプローチで実際の基準を実行することで、これを簡単に比較できます。
user7370003
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.