楽観的ロックと悲観的ロックの違いを理解しています。一般的にどちらを使用するかを誰かに説明してもらえますか?
また、クエリを実行するためにストアド プロシージャを使用しているかどうかによって、この質問に対する答えは変わりますか?
ただし、楽観的とは「読み取り中にテーブルをロックしない」ことを意味し、悲観的とは「読み取り中にテーブルをロックする」ことを意味します。
楽観的ロックと悲観的ロックの違いを理解しています。一般的にどちらを使用するかを誰かに説明してもらえますか?
また、クエリを実行するためにストアド プロシージャを使用しているかどうかによって、この質問に対する答えは変わりますか?
ただし、楽観的とは「読み取り中にテーブルをロックしない」ことを意味し、悲観的とは「読み取り中にテーブルをロックする」ことを意味します。
楽観的ロックは、レコードを読み取り、バージョン番号をメモし (日付、タイムスタンプ、またはチェックサム/ハッシュを使用する他の方法があります)、レコードを書き戻す前にバージョンが変更されていないことを確認する戦略です。レコードを書き戻すときは、バージョンの更新をフィルタリングして、アトミックであることを確認します。(つまり、バージョンを確認してからレコードをディスクに書き込むまでの間に更新されていない)、バージョンを 1 ヒットで更新します。
レコードが汚れている (つまり、自分のバージョンとは異なる) 場合は、トランザクションを中止し、ユーザーはトランザクションを再開できます。
この戦略は、セッションのために必ずしもデータベースへの接続を維持する必要のない大容量システムおよび 3 層アーキテクチャーに最も適しています。この状況では、接続がプールから取得され、あるアクセスから次のアクセスまで同じ接続を使用していない可能性があるため、クライアントは実際にはデータベース ロックを維持できません。
悲観的ロックとは、レコードを使い終わるまで排他的に使用するためにレコードをロックすることです。楽観的ロックよりも整合性がはるかに優れていますが、デッドロックを回避するためにアプリケーションの設計に注意する必要があります。ペシミスティック ロックを使用するには、データベースへの直接接続 (通常は2 層のクライアント サーバーアプリケーションの場合) か、接続とは独立して使用できる外部で使用可能なトランザクション ID が必要です。
後者の場合、TxID でトランザクションを開き、その ID を使用して再接続します。DBMS はロックを維持し、TxID を介してセッションをバックアップできるようにします。これが、2 フェーズ コミット プロトコル ( XAやCOM+ トランザクションなど) を使用した分散トランザクションのしくみです。
オプティミスティック ロックは、多くの衝突が予想されない場合に使用されます。通常の操作を行うにはコストがかかりませんが、競合が発生した場合、トランザクションが中止されるため、それを解決するために高い代償を支払うことになります。
悲観的ロックは、衝突が予想される場合に使用されます。同期に違反するトランザクションは単純にブロックされます。
適切なロック メカニズムを選択するには、読み取りと書き込みの量を見積もり、それに応じて計画する必要があります。
楽観的は、あなたがそれを読んでいる間は何も変わらないと仮定します。
悲観的は、何かがそうするだろうと想定し、それをロックします。
データが完全に読み取られることが必須でない場合は、楽観的を使用します。奇妙な「汚い」読み取りが発生する可能性がありますが、デッドロックなどを引き起こす可能性ははるかに低くなります。
ほとんどの Web アプリケーションは、ダーティ リードを使用しても問題ありません。まれに、次のリロードでデータが正確に集計されないことがあります。
正確なデータ操作 (多くの金融取引のように) には、悲観的を使用します。表示されていない変更がなく、データが正確に読み取られることが不可欠です。追加のロック オーバーヘッドはそれだけの価値があります。
ああ、そしてMicrosoft SQLサーバーはデフォルトでページをロックします - 基本的にあなたが読んでいる行とその両側のいくつか。行のロックはより正確ですが、はるかに遅くなります。読み取り中のデッドロックを回避するために、トランザクションを read-committed または no-lock に設定する価値があることがよくあります。
悲観的ロックがより良い選択になるもう 1 つのケースを考えてみます。
楽観的ロックの場合、データ変更のすべての参加者は、この種のロックの使用に同意する必要があります。しかし、誰かがバージョン列を気にせずにデータを変更すると、楽観的ロックの考え方全体が台無しになります。
基本的に、最も一般的な回答は 2 つあります。最初のものは基本的に言う
オプティミスティックには、セッションのデータベースへの接続を必ずしも維持する必要のない 3 層アーキテクチャが必要ですが、ペシミスティック ロックは、レコードを使い終わるまで排他的に使用するためにレコードをロックする場合です。データベースへの直接接続が必要な楽観的ロックよりも整合性がはるかに優れています。
楽観的 (バージョン管理) はロックがないため高速ですが、競合が多い場合は (悲観的) ロックのパフォーマンスが向上し、作業を破棄して最初からやり直すよりも回避する方が適切です。
また
オプティミスティック ロックは、まれに衝突が発生する場合に最適に機能します
このページに掲載されている通りです。
「接続を維持する」が「衝突が少ない」とどのように関連しているかを説明するために、回答を作成しました。
どの戦略が最適かを理解するには、DB の 1 秒あたりのトランザクション数ではなく、1 つのトランザクションの期間を考えてください。通常、トランザクションを開き、操作を実行して、トランザクションを閉じます。これは、ANSI が念頭に置いていた短い古典的なトランザクションであり、ロックを回避しても問題ありません。しかし、多くのクライアントが同じ部屋/座席を同時に予約するチケット予約システムをどのように実装しますか?
オファーを閲覧し、利用可能なオプションと現在の価格をフォームに入力します。多くの時間がかかり、オプションが時代遅れになる可能性があります。フォームへの入力を開始して「同意する」ボタンを押すまでの間のすべての価格は無効です。これは、アクセスしたデータにロックがなく、より機敏な他の誰かが干渉したためですすべての価格を変更すると、新しい価格で再起動する必要があります。
代わりに、すべてのオプションを読みながらロックすることができます。これは悲観的なシナリオです。なぜそれがひどいのかがわかります。あなたのシステムは、予約を開始してタバコを吸う 1 人のピエロによってダウンする可能性があります。彼が終わる前に誰も何かを予約することはできません。あなたのキャッシュフローはゼロになります。そのため、実際には楽観的な留保が使用されます。あまりにも長くぶらぶらしている人は、より高い価格で予約を再開する必要があります.
この楽観的なアプローチでは、読み取ったすべてのデータを記録し (私の Repeated Readのように)、データのバージョンでコミット ポイントに到達する必要があります (現在の価格ではなく、この見積もりで表示された価格で株を購入したい) )。この時点で、ANSI トランザクションが作成され、DB がロックされ、何も変更されていないかどうかがチェックされ、操作がコミット/中止されます。IMO、これはMVCCの効果的なエミュレーションです。これは Optimistic CC にも関連付けられており、アボートの場合にトランザクションが再開されること、つまり新しい予約を行うことも前提としています。ここでのトランザクションには、人間のユーザーの決定が含まれます。
MVCC を手動で実装する方法を理解するにはほど遠いですが、再起動のオプションを使用した長期実行トランザクションが主題を理解するための鍵であると思います。どこか間違っている場合は修正してください。私の答えは、このアレックス・クズネコフの章に動機付けられました。
ほとんどの場合、楽観的ロックはより効率的で、より高いパフォーマンスを提供します。悲観的ロックと楽観的ロックのどちらかを選択する場合は、次の点を考慮してください。
悲観的ロックは、多数の更新があり、ユーザーが同時にデータを更新しようとする可能性が比較的高い場合に役立ちます。たとえば、各操作が一度に多数のレコードを更新できる場合 (銀行は毎月末にすべての口座に利子収入を追加する可能性があります)、2 つのアプリケーションがそのような操作を同時に実行すると、競合が発生します。 .
ペシミスティック ロックは、頻繁に更新される小さなテーブルを含むアプリケーションにも適しています。これらのいわゆるホットスポットの場合、競合が発生する可能性が非常に高いため、楽観的ロックでは競合するトランザクションをロールバックする労力が無駄になります。
オプティミスティック ロックは、競合の可能性が非常に低い場合に役立ちます。レコードは多いがユーザーが比較的少ない場合、または更新がほとんどなく、ほとんどが読み取りタイプの操作である場合です。
オプティミスティック ロックとペシミスティック ロックは、データベース内のデータをロックするための 2 つのモデルです。
楽観的ロック: 変更がデータベースにコミットされた場合にのみ、レコードがロックされます。
悲観的ロック: 編集中にレコードがロックされる場所。
注: どちらのデータ ロック モデルでも、変更がデータベースにコミットされた後にロックが解除されます。