MySQL における楽観的ロック、悲観的ロック、MVCC の包括的な分析

MySQL における楽観的ロック、悲観的ロック、MVCC の包括的な分析

序文

データベースの実際の使用では、データの書き込みや読み取りを同時に行わないことが必要な状況によく遭遇します。たとえば、フラッシュセールのシナリオでは、2 つのリクエストが同時に、システムにまだ在庫が 1 個あることを読み取り、その後、在庫を 0 に更新します。これにより、売れ過ぎの状況が発生し、商品の実際の在庫が記録と一致しなくなります。

リソースの競合によって生じるデータの不整合などの問題を解決するには、データへの正しいアクセスと変更を保証するメカニズムが必要です。データベースでは、このメカニズムがデータベースの同時実行制御です。その中で、楽観的同時実行制御、悲観的同時実行制御、およびマルチバージョン同時実行制御は、データベース同時実行制御に使用される主な技術的手段です。

悲観的同時実行制御

自然

Wikipedia: リレーショナル データベース管理システムでは、悲観的同時実行制御 (「悲観的ロック」とも呼ばれ、略して「PCC」) は同時実行制御の方法です。トランザクションが他のユーザーに影響を与えるような方法でデータを変更することを防ぎます。トランザクションがデータ行を読み取ってロックを適用する操作を実行する場合、そのトランザクションがロックを解除すると、他のトランザクションはロックと競合する操作のみを実行できるようになります。

実は、私たちがよく話題にする悲観的ロックは実際のロックではなく、並行性制御の考え方です。悲観的並行性制御はデータの変更に対して悲観的であり、外部からデータにアクセスすると必然的に競合が発生すると考えています。そのため、データ処理のプロセスではロックを使用して、リソースの排他的使用を確保します。

データベースロックの仕組みは、実際には悲観的同時実行制御の観点から実装されており、実際の使用状況に応じて、データベースロックは多くのカテゴリに分類できます。詳細については、後の記事を参照してください。

実装

データベース悲観的ロックのロック プロセスは次のとおりです。

トランザクションを開始した後、操作の種類に応じてロックが必要なデータに特定の種類のロックを適用します。たとえば、共有行ロックなどです。ロックが成功した場合は、後続の操作を続行します。データが他のロックによってロックされており、今追加するロックと競合する場合、ロックは失敗します (たとえば、排他ロックが追加された場合)。このとき、他のロックが解除されるのを待つ必要があります (デッドロックが発生する可能性があります)
トランザクションが完了したらロックを解除します

長所と短所

アドバンテージ:

悲観的同時実行制御では、「最初にロックを取得し、成功したらデータにアクセスする」という保守的な戦略を採用しています。これにより、データの取得と変更が秩序正しく実行されるため、書き込みが多く読み取りが少ない環境での使用に適しています。もちろん、悲観的ロックを使用すると非常に高いパフォーマンスを維持することはできませんが、楽観的ロックではより良いパフォーマンスが得られないという前提の下では、悲観的ロックはデータのセキュリティを確保できます。

欠点:
ロックが必要であり、ロックの競合やデッドロックが発生する可能性があるため、悲観的同時実行制御ではシステムのオーバーヘッドが増加し、システム効率が低下し、システムの並列性も低下します。

楽観的同時実行制御

自然

Wikipedia: リレーショナル データベース管理システムでは、楽観的同時実行制御 (「楽観的ロック」、楽観的同時実行制御とも呼ばれ、略して「OCC」) は同時実行制御方式です。複数ユーザーの同時トランザクションは処理中に互いに影響を及ぼさず、各トランザクションはロックを生成せずに影響を受けるデータの一部を処理できることを前提としています。
楽観的同時実行制御は、データの変更について楽観的であり、同時実行環境であっても、データに対する外部操作によって通常は競合が発生しないと考えているため、データをロックしません。代わりに、各トランザクションは、データの更新を送信する前に、まず、トランザクションがデータを読み取った後に他のトランザクションがデータを変更したかどうかを確認します。他のトランザクションがトランザクションを更新した場合、競合情報が返され、ユーザーは再試行やロールバックなどの続行方法を決定できます。

楽観的ロックは実際にはロックではなく、同時実行制御を実装するためにロックも使用していないことがわかります。代わりに、他の方法を使用して、データが変更可能かどうかを判断します。楽観的ロックは、通常、ユーザーによって実装されるロック メカニズムです。実際のロックは使用されませんが、ロック効果を生み出すことができます。

実装

CAS (Compare and swap) は、よく知られているロックフリー アルゴリズムです。ロックフリープログラミングとは、ロックを使用せずに複数のスレッド間で変数の同期を実現すること、つまりスレッドがブロックされることなく変数の同期を実現することを意味し、ノンブロッキング同期とも呼ばれます。非ブロッキング同期を実装する方式は、「ロックフリー プログラミング アルゴリズム」と呼ばれます。

楽観的ロックは基本的に CAS (Compare and swap) アルゴリズムに基づいて実装されます。まず、CAS プロセスを見てみましょう。CAS 操作のプロセスは、次の C コードで表すことができます。

int cas(long *addr, long old, long new)
{
 /* アトミックに実行します。 */
 if(*addr != 古い)
  0を返します。
 *addr = 新しい;
 1 を返します。
}

CAS には、メモリ値 V、古い期待値 A、および変更される新しい値 B の 3 つのオペランドがあります。期待値 A とメモリ値 V が同じ場合のみ、メモリ値 V を B に変更し、それ以外の場合は何もしません。 CAS 操作全体はアトミック操作であり、分割できません。

楽観的ロックの実装は、主に次の点で上記のプロセスと似ています。

  • バージョン番号タグ: テーブルに新しいフィールド「version」を追加します。これはバージョン番号を保存するために使用されます。データを取得するときに、同時にバージョン番号を取得し、次のコマンドを使用してデータを更新します: update xxx set version=version+1,… ここで、… version="old version" であり、… です。このとき、返された結果内の影響を受けた行数が 0 であるかどうかを判断して、更新が成功したかどうかを判断します。更新が失敗した場合は、他のリクエストによってすでにデータが更新されていることを意味します。
  • タイムスタンプ: バージョン番号と同じですが、タイムスタンプによって決定されます。一般的に、多くのデータテーブルには更新時刻フィールドがあります。このフィールドを使用して判断することで、新しいフィールドを追加する必要はありません。
  • 更新するフィールド: タイムスタンプ フィールドがなく、新しいフィールドを追加したくない場合は、更新するフィールドを使用して判断することを検討できます。更新されたデータは一般的に変更されるため、更新する前に、更新するフィールドの古い値とデータベースの現在の値を比較できます。変更がない場合は更新します。
  • すべてのフィールド マーク: データ テーブル内のすべてのフィールドが判断に使用されます。これは、いくつかのフィールドだけでなく、データ行全体をロックするのと同じです。この行のデータが変更される限り、更新されません。

長所と短所

アドバンテージ:

楽観的同時実行制御では、実際にはロックが行われないため、追加のオーバーヘッドがなく、デッドロックの問題が発生する可能性は低くなります。読み取りが多く書き込みが少ない同時実行シナリオに適しています。追加のオーバーヘッドがないため、データベースのパフォーマンスを大幅に向上できます。

欠点:
楽観的同時実行制御は、書き込みが読み取りよりも多い同時実行シナリオには適していません。書き込みの競合が多く発生し、データの書き込みに複数の待機と再試行が発生するためです。この場合、そのオーバーヘッドは実際には悲観的ロックよりも高くなります。さらに、楽観的ロックのビジネス ロジックは悲観的ロックのビジネス ロジックよりも複雑です。ビジネス ロジックでは、失敗や再試行の待機を考慮する必要があり、他のサードパーティ システムによるデータベースへの直接的な変更を回避することはできません。

マルチバージョン同時実行制御

自然

Wikipedia: 多版型同時実行制御 (MCC または MVCC) は、データベース管理システムで一般的に使用される同時実行制御の一種であり、トランザクション メモリを実装するプログラミング言語でも使用されます。

楽観的同時実行制御と悲観的同時実行制御はどちらも、対応するトランザクションを遅延または終了することでトランザクション間の競合状態を解決し、トランザクションの直列化可能性を保証します。前の 2 つの同時実行制御メカニズムは、同時トランザクションの直列化可能性の問題を根本的に解決できますが、実際には書き込み競合の問題を解決しています。2 つの違いは、書き込み競合に関する楽観度の違いにあります (悲観的ロックも読み取り/書き込み競合を解決できますが、パフォーマンスは平均的です)。実際の使用では、データベースの読み取り要求は書き込み要求の数倍になります。読み取りと書き込みの同時実行の問題を解決できれば、データベースの読み取りパフォーマンスを大幅に向上させることができます。これが、マルチバージョン同時実行制御で実現できることです。

悲観的同時実行制御や楽観的同時実行制御とは異なり、MVCC は、読み取り/書き込みロックによって複数の長期読み取り操作が書き込み操作を枯渇させる問題、つまり読み取り/書き込み競合の問題を解決するように設計されています。 MVCC は、前の 2 つのメカニズムのいずれかと組み合わせて使用​​することで、データベースの読み取りパフォーマンスを向上させることができます。

データベースの悲観的ロックは、同時実行パフォーマンスの向上を考慮したものであり、一般的にはマルチバージョン同時実行制御を同時に実装します。 MySQL だけでなく、Oracle、PostgreSQL などの他のデータベース システムでも MVCC が実装されていますが、MVCC には統一された実装標準がないため、実装メカニズムはそれぞれ異なります。

一般的に、MVCC の出現は、パフォーマンスが低いために悲観的ロックを使用して読み取り書き込み競合問題を解決することに不満があるため、データベースによって提案されたソリューションです。

実装

MVCC は、特定の時点でのデータのスナップショットを保存することによって実装されます。各トランザクションで読み取られるデータ項目は、履歴スナップショットであり、スナップショット読み取りと呼ばれます。現在の読み取りとは異なり、スナップショット読み取りで読み取られるデータは最新のものではない可能性がありますが、スナップショット分離により、トランザクション全体で見られるデータは、開始時のデータ状態であることが保証されます。書き込み操作では既存のデータ項目は上書きされませんが、トランザクションがコミットされたときにのみ表示される新しいバージョンが作成されます。

現在の読み取りとスナップショットの読み取り

MySQL InnoDB の現在の読み取りとスナップショット読み取りとは何ですか?

共有モードでのロックの選択 (共有ロック)、更新の選択、更新、挿入、削除 (排他ロック) などの現在の読み取り操作はすべて現在の読み取りです。なぜ現在の読み取りと呼ばれるのでしょうか?つまり、レコードの最新バージョンを読み取ります。読み取り時には、他の同時トランザクションが現在のレコードを変更できないようにする必要があり、読み取られたレコードはロックされます。

スナップショット読み取りは、ロックなしの選択操作、つまりロックなしの非ブロッキング読み取りに似ています。スナップショット読み取りの前提は、分離レベルが非コミット読み取りやシリアル化レベルではないことです。これは、非コミット読み取りでは、現在のトランザクション バージョンに準拠するデータ行ではなく、常に最新のデータ行が読み取られるためです。シリアル化により、読み取られたすべての行がロックされます。

長所と短所

MVCC では、ロックなしでほとんどの読み取り操作を実行できます。この設計により、データの読み取り操作が簡単になり、パフォーマンスが向上し、条件を満たす行のみが読み取られるようになります。欠点は、レコードの各行ごとに追加のストレージ スペース、行のチェック作業、および追加のメンテナンス作業が必要になることです。

適用可能なシナリオ

悲観的ロック

読み取りと書き込みの競合や書き込みと書き込みの競合を解決するために使用されるロック同時実行制御は、読み取りよりも書き込みが多く、書き込みの競合が深刻な状況に適しています。悲観的ロックはデータの読み取り時にロックされるため、読み取りが多いシナリオでは頻繁なロックと長い待機時間が必要になります。深刻な書き込み競合の場合は、悲観的ロックを使用することでデータの一貫性を確保できます。高いデータ一貫性要件により、ダーティ リード、ファントム リード、非反復読み取り、ファースト クラス更新損失、セカンド クラス更新損失などの問題を解決できます。

楽観的ロック

書き込み競合を解決するロックフリー同時実行制御は、書き込みよりも読み取りが多い状況に適しています。書き込み操作の数が多いと、書き込み競合の可能性が高まり、ビジネス層が継続的に再試行する必要があり、システムパフォーマンスが大幅に低下するためです。データの一貫性要件は高くありませんが、非常に高い応答速度が必要です。ダーティリード、ファントムリード、非反復読み取りは解決できませんが、更新損失の問題を解決できます。

MVCC

読み取り書き込み競合を解決するロックフリーの同時実行制御を上記2つと組み合わせることで、読み取りパフォーマンスが向上します。

上記は、MySQL における楽観的ロック、悲観的ロック、および MVCC の包括的な分析の詳細な内容です。MySQL における楽観的ロック、悲観的ロック、および MVCC の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL の分離レベル、ロック、MVCC の紹介
  • MySQL ストレージ エンジン MyISAM と InnoDB の違いの概要
  • MySQLでデータテーブルを作成するときにエンジンMyISAM/InnoDBを設定する
  • MySQL InnoDB ストレージエンジンのメモリ管理の詳細な説明
  • MySQLのInnoDBストレージエンジンにおけるさまざまなロックの詳細な説明
  • MySQLのInnoDBストレージエンジンのデータページ構造の詳細な説明
  • MySQL ストレージ エンジン InnoDB と MyISAM
  • MYSQL データベース Innodb エンジン mvcc ロック実装原理

<<:  Vueはページdivボックスのドラッグアンドドロップソート機能を実装します

>>:  Docker用国産イメージウェアハウスの使い方

推薦する

Linux での mysql8.018 のインストールと設定のプロセスの詳細な説明

Windowsでのインストールの紹介:こちらもご覧ください –》WindowsでのMySQL 8.0...

MySQLの起動と接続方法の例分析

目次mysqldの起動方法方法 1: mysqld方法 2: mysqld_safe方法3: mys...

MySQLカーソルの使い方と機能の詳細な説明

[mysqlカーソルの使い方と機能]例:現在、テーブル A、B、C の 3 つのテーブルがあります。...

MySQLサービスの自動停止の解決策

この記事では主に、MySQL サービスの自動停止の解決策を紹介し、参考と学習のために共有します。一緒...

Iframe の内外のページで JS がどのように動作するかの概要

目次iframeの外側のiframeのコンテンツを取得する方法1方法2 iframe 内の ifra...

Linux ディスク管理 LVM の使用

1. LVM の概要Linux ディスクを管理するときに、このような状況に遭遇することがよくあります...

完全なショッピングカートを実装するためのミニプログラム

ミニプログラムは、参考までに完全なショッピングカート[すべて選択/選択解除して金額を計算/加算と減算...

初心者のためのウェブサイト構築入門 - ウェブサイト構築に必要な条件とツール

今日は、初心者の次のような質問に答えます。学ぶ勇気さえあれば、自分のウェブサイトを構築するのは簡単で...

IDEA が MySQL データベースに接続できない問題の 6 つの解決策

この記事では、IDEA が MySQL データベースに接続できない問題に対する 6 つの解決策を主に...

VueはEChartsを使用して折れ線グラフと円グラフを実装します

バックエンド管理プロジェクトを開発する場合、バックエンドのユーザーデータをカウントし、折れ線グラフや...

MySQLでトリガーを作成する方法

この記事の例では、参考のためにMySQLトリガーを作成するための具体的なコードを共有しています。具体...

JavaScript でじゃんけんゲームを書く

この記事では、JavaScriptでじゃんけんゲームを書くための具体的なコードを参考までに紹介します...

2013年のウェブデザインUIの最もホットなトレンド最も人気のあるUIデザイン

時は経つのが早く、わずか 6 日後には 2013 年が歴史になります。今年は、いわゆるトレンドが多す...

Nginx+FastDFSでイメージサーバーを構築

設置環境セントス環境依存性: yum -y gccをインストールします yum インストール -y ...

Apache での ab パフォーマンス テスト結果を分析する

私はパフォーマンス テストを行うために常に Loadrunner を使用してきました。 Loadru...