トランザクション独立性レベル(2)

4186 ワード

今日はMySQLデータベースの観点からロックメカニズムとトランザクション独立性レベルの関係を説明します.
MySQLデータベースは複数のデータベースエンジンをサポートしていますが、最も一般的なのはMyISAMとInnoDBだけです.MyISAMはトランザクションをサポートしていないため、トランザクションの独立性レベルについてはInnoDBについて話しています.ただし,MyISAMで使用される表レベルロックはInnoDB上の行レベルロックを理解するのに役立つため,本稿では要約する.
一、同時取引と取引の隔離レベル
単一スレッドのデータ処理に比べて、同時トランザクションはデータベース・リソースの使用率を大幅に向上させ、データベース・システムのトランザクション・スループットを向上させ、より多くのユーザーをサポートします.しかし、同時にいくつかの問題をもたらします.
  • 更新を失う:複数のトランザクションが同じローのデータを同時に更新し、最初に選択した値に基づいて操作を実施すると、トランザクションの独立性により互いに相手の存在を知らない.これにより、最後の更新が他のすべてのトランザクションの更新を上書きします.
  • ダーティリード:トランザクションがレコードを変更しており、トランザクションがコミットされる前に現在のレコードが不安定になっています.このとき、別のトランザクションもこのレコードを読み取りに来ます.制御を加えないと、2番目のトランザクションが汚いデータを読み取り、コミットされていないデータに依存する可能性があります.この現象を「汚い読み」と呼ぶ.
  • は繰り返して読むことはできません:1つのトランザクションがいくつかのデータを読み取った後のある時間、再び以前に読み取ったデータを読み取ってみて、データが修正または削除されたことを発見します.この現象を「繰り返してはいけない」と言います.
  • 幻読:1つのトランザクションが同じ条件でクエリーする前に取得したレコードですが、他のトランザクションが新しいデータを挿入していることがわかります.この現象を「幻読」と呼ぶ.

  • 失われた更新は、データベース・トランザクション・コントローラに完全に依存することはできません.更新する必要があるデータにアプリケーションが必要なロックを追加して解決する必要があります.したがって、更新の紛失を防止することはアプリケーションの責任です.スレッドの同時性の観点から、データを更新する可能性のある方法で同期する必要があります.
    データベースがトランザクション・アイソレーションを実現する方法は、基本的に2つに分けられます.
    1つは、データを読み込む前にロックし、他のトランザクションがデータを変更することを阻止することです.
    もう1つは、ロックを追加するのではなく、一定のメカニズムによってデータ要求ポイントのコンシステンシデータスナップショットを生成し、このスナップショットを使用して一定レベルのコンシステンシ読み出し操作を提供することである.
    データベースのトランザクション・アイソレーションが厳しいほど、同時実行の副作用は小さくなりますが、コストは大きくなります.トランザクション・アイソレーションは、実質的にトランザクションをある程度「シーケンス化」させるため、同時性とは明らかに矛盾しています.上記の矛盾を解決するために、MySQLでは、コミットされていない読み取り、コミットされた読み取り、繰り返し可能読み取り、シーケンス可能という4つのトランザクション独立性レベルが定義されています.具体的な定義は前の記事を参考にしてください.ここでは後述しません.
    二、InnoDBの行レベルロックモード
    InnoDBには、2種類の行レベルロックとそれに一致するテーブルレベルロックが用意されています.
  • 行共有ロック:他のトランザクションの読み取りを許可しますが、排他ロックの取得を阻止します.
  • 行排他ロック:現在のトランザクションはデータの読み取りと更新を許可するが、他のトランザクションは操作データセットの行共有ロックと行排他ロックを取得することを阻止する.
  • テーブル共有ロック(意向共有ロック):トランザクションはデータ行に共有ロックを追加するつもりで、まずそのデータテーブルのテーブル共有ロックを取得する必要があります.
  • 表排他ロック(意向排他ロック):トランザクションはデータ行に排他ロックを追加するつもりで、まずこのデータ表の表排他ロックを取得する必要があります.

  • 1つのトランザクションがデータ・テーブルのテーブル・排他ロックを取得すると、別のトランザクションもこのデータ・テーブルの排他ロックを取得できます.2つの更新データのトランザクションは競合しないため、更新が失われた問題はアプリケーション・レイヤに任せて解決する必要があります.このことから,InnoDBによるロックの実装は文字通りよりも明らかに複雑である.これは,InnoDBのテーブルレベルロックを意図ロックと呼ぶことが多い理由であり,MyISAMのテーブルレベルロックとは根本的に異なる.
    具体的なロックの操作については、本明細書の議論の範囲外である.
    三、MyISAMの表級ロックモード
    MyISAMエンジンはトランザクションをサポートしていないため、トランザクションの同時発生という問題はありません.MyISAMのテーブル・レベル・ロックには、テーブル共有リード・ロックとテーブル・ライト・ロックの2つのモードがあります.意味の違いを除いて、InnoDBとの違いは主に以下の2点である.
  • MyISAMがテーブルにロックをかけるのは、テーブルに関連するすべてのロックを同時に取得することであり、InnoDBは徐々にロックを取得することである.このためMyISAMではデッドロックは発生しません.逆に言えば,この特徴の存在により,実際の実行では書き込みプロセスが読み取りプロセスよりも優先される.そのためMyISAMでは読み取りプロセスが常にブロックされる場合がありますが、InnoDBではこのような問題は発生しません.
  • MyISAMエンジンを使用して共有リードロックを取得したスレッドは、現在の時点で他のスレッドがデータテーブルを操作しているかどうかにかかわらず、リード操作のみを行い、更新と増加はできません.またMyISAMはロックレベルを自動的に上げることができないため、共有ロックを取得したスレッドが更新または増加するには、共有ロックを解除してから排他ロックを取得しようとしなければならない.InnoDBエンジンは自動的にロックレベルを上げることができ、読み出しトランザクションは現在のデータセットに他のトランザクションアクセスがない場合に関連データを更新することができ、効率が高い.

  • 四、InnoDB行レベルロックの特殊性
    以上の内容を理解することができ、基本的にMySQLのロックメカニズムと物事の隔離に対して比較的正確な認識を持っている.補足として、MySQLデータベースとOracleの違いを追加します.
    InnoDB行レベルのロックは、インデックス上のインデックス・アイテムにロックをかけることによって実現されます.これはOracleとは異なり、データ・ブロックに対応するデータ行にロックをかけることによって実現されます.この特徴は、インデックス条件でデータを取得する場合にのみ、InnoDBがロー・レベル・ロックを使用できることを意味します.そうしないと、テーブル・レベル・ロックのみが使用され、同時パフォーマンスに大きな影響を及ぼします.また、異なるレコードにアクセスしても、トランザクションが同じインデックスキーを使用している場合、ロック競合が発生します.
    範囲インデックスを使用して共有ロックまたは排他ロックを要求すると、キー値が存在しないレコードに対してInnoDBはギャップロックを使用します.例:
    Select * From user where id>100 for update;

    InnoDBは、条件を満たすすべてのレコードにロックをかけるだけでなく、id>100の存在しないレコードにもギャップロックをかける.ギャップロックを使用する目的は主に幻読の発生を防止することである.この点はMyISAMとも違います.MyISAMエンジンを使用して、リードスレッドに共有リードロックを加えたデータテーブルは、他のライトスレッドによってテーブルの最後からレコードを挿入することができます.したがって、前述の「スナップショット」技術を使用しない限り、MyISAMを使用した読み取り操作に「幻読み」の問題が発生しないことを保証することは困難である.