Chanler

Chanler

「黒馬 MySQL」二、InnoDB エンジン

論理ストレージ構造#

image.png|500

InnoDB ストレージエンジンでは、各行のデータはテーブルで定義されたすべてのフィールドの値に加えて、以下の重要な情報も含まれています:

  1. 6 バイトのトランザクション ID trx id
    InnoDB では、各トランザクションに一意のトランザクション ID が付与され、各行のデータにはこのトランザクション ID の値が含まれ、トランザクションレベルのマルチバージョン同時実行制御 MVCC を実現します。
  2. 7 バイトのロールバックポインタ roll pointer
    トランザクションのロールバック操作をサポートするために、各行のデータにはロールバックログ内の対応するレコードを指すロールバックポインタが含まれています。トランザクションがロールバックを必要とする場合、ロールバックポインタを使用して迅速に対応するロールバックレコードを特定し、データを復元できます。
  3. 非 NULL 列ビットマップ
    非 NULL 列ビットマップは、InnoDB ストレージエンジンでストレージ効率を向上させるためのメカニズムです。テーブル内には多くの列が NULL 値であることが多いため、これらの列の情報をビットマップの形式で表現することで、データを保存する際に可能な限りストレージスペースを圧縮します。
  4. レコードヘッダー
    各行のデータにはレコードヘッダーが含まれており、データが削除されたかどうか、ロックされているかどうかなどのメタデータ情報が含まれています。
  5. バージョン番号
    InnoDB の MVCC 実装では、各行のデータにはバージョン番号が含まれており、現在の行のバージョン情報を示します。トランザクションが行のデータを更新すると、実際には元の行のデータに基づいて新しいレコードが追加され、バージョン番号によってこれらの 2 つのレコードを区別します。

以上のように、InnoDB の行 ROW にはテーブルで定義されたフィールドの値に加えて、多くの他のメタデータ情報が含まれており、InnoDB ストレージエンジンはトランザクションサポート、MVCC、ストレージ効率、データ復元などの面で重要な役割を果たしています。

アーキテクチャ#

以下は InnoDB のアーキテクチャ図で、左側がメモリ構造、右側がディスク構造です。

image.png|500

メモリ構造 - バッファプール Buffer Pool#

操作キャッシュプールのデータを一定の頻度でディスクにフラッシュし、ディスク IO を減少させます。

image.png|500

バッファプールはページ Page 単位で管理され、底層はリンクリストで管理され、3 種類に分かれています:

  1. free page:空いているページ、未使用
  2. clean page:使用されたページだが、データが変更されていない
  3. dirty page:汚れたページ、使用されたページでデータが変更されている。この時、データはディスクのデータと不一致になり、ディスクにフラッシュする必要があります。

メモリ構造 - 変更バッファ Change Buffer#

データの変更を変更バッファにキャッシュし、将来データが読み込まれるときにデータをマージしてバッファプールに復元します。その後、マージされたデータはディスクにフラッシュされます。

image.png|500

変更バッファ Change Buffer の存在意義:
二次インデックスは通常一意ではなく、挿入が比較的ランダムで、削除変更操作の影響範囲が広く、大量のディスク IO を引き起こします。まずバッファプール Buffer Pool でデータをマージすることで、ディスク IO を減少させることができます。

メモリ構造 - 自適応ハッシュインデックス Adaptive Hash Index#

バッファプールのデータクエリを最適化します。

image.png|500

メモリ構造 - ログバッファ Log Buffer#

ログバッファは redo log、undo log などのログデータを保存し、デフォルトは 16MB で、定期的にディスクにフラッシュし、大量の操作頻繁なディスク IO を減少させます。

image.png|500

ディスク構造 - システムテーブルスペース System Tablespace#

image.png|500

ディスク構造 - ファイルテーブルスペース File-Per-Table Tablespaces:#

image.png|500

ディスク構造 - 一般テーブルスペース General Tablespaces#

image.png|500

ディスク構造 - アンデーテーブルスペース Undo Tablespaces 一時テーブルスペース Temporary Tablespaces#

image.png|500

ディスク構造 - ダブル書きバッファ Doublewrite Buffer Files 再実行ログ Redo Log#

image.png|500

バックグラウンドスレッド#

バックグラウンドスレッドの役割:メモリをディスクにフラッシュします。

image.png|500

トランザクションの原理#

トランザクションは一連の操作の集合であり、不可分の作業単位です。トランザクションはすべての操作を一つの全体としてシステムに提出または取り消しの操作リクエストを行います。つまり、これらの操作は同時に成功するか、同時に失敗する必要があります。

ACID 特性

  • 原子性 Atomicity:トランザクションは不可分の最小操作単位であり、すべて成功するか、すべて失敗する必要があります。
  • 一貫性 Consistency:トランザクションが完了する際、すべてのデータが一貫した状態を維持する必要があります。
  • 隔離性 Isolation:データベースシステムが提供する隔離メカニズムにより、トランザクションは外部の同時操作の影響を受けない独立した環境で実行されます。
  • 永続性 Durability:トランザクションが一度提出またはロールバックされると、それがデータベース内のデータに対する変更は永続的なものとなります。

原子性 - undo log
永続性 - redo log
一貫性 - undo log + redo log
隔離性 - ロック + MVCC

redo log - 永続性#

汚れたページがディスクにフラッシュされる際にエラーが発生した場合、redo log に基づいてデータを復元します。

image.png|500

WAL write-ahead logging は、まずログを書き、ログは追加で書き込まれ、順序ディスク IO であり、汚れたページのランダムディスク IO ではありません。

undo log - 原子性#

ロールバックログ undo log は、データが変更される前の情報を記録し、ロールバック rollback と MVCC を提供します。

undo log は主にロールバックに適しているため、記録は論理ログであり、逆の操作文を記録します。これにより、ロールバックは対応する内容を読み取ってロールバックできます。

image.png|500

MVCC#

RU:最近のデータを直接読み取ります。MVCC はなく、ロックもなく、何もありません。
RC:毎回の読み取りでスナップショット読み取りを生成し、最新のコミットされたデータを読み取ることができます。
RR:トランザクション開始後の最初の select 文がスナップショット読み取りを生成し、その後はこの readview を継続して使用し、再現可能な読み取りを保証します。
SE:毎回現在の読み取りで、ブロックされ、ロックもかかります。

現在の読み取り:
読み取っているのはレコードの最新バージョンであり、読み取り時に他の同時トランザクションが現在のレコードを変更できないことを保証するために、読み取っているレコードにロックをかけます。例えば:
select..lock in share mode 共有ロック、select..for update、update、insert、delete 排他ロックはすべて現在の読み取りの一種です。

スナップショット読み取り:
単純な select(ロックなし)はスナップショット読み取りであり、スナップショット読み取りはレコードデータの可視バージョンを読み取ります。歴史的なデータである可能性があり、ロックなしで非ブロッキング読み取りです。

  • Read Committed:毎回 select でスナップショット読み取りを生成します。
  • Repeatable Read:トランザクション開始後の最初の select 文がスナップショット読み取りの場所です。
  • Serializable:スナップショット読み取りは現在の読み取りに退化します。

MVCC:
正式名称はマルチバージョン同時実行制御であり、データの複数のバージョンを維持し、読み取りと書き込みの操作に衝突がないようにします。スナップショット読み取りは MySQL が MVCC を実現するための非ブロッキング読み取り機能を提供します。
MVCC の具体的な実装は、データベースレコード内の 3 つの暗黙のフィールド、undo log ログ、readView に依存しています。

実装原理 - 3 つの暗黙のフィールド#

DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID

image.png|500

実装原理 - undo log ログ#

ロールバックログ undo log は、insert、update、delete 時に生成され、データのロールバックのためのログです。
insert によって生成された undo log はロールバック時にのみ必要であり、トランザクションがコミットされた後は即座に削除できます。
update、delete によって生成された undo log はロールバック時だけでなく、スナップショット読み取り時にも必要であり、即座には削除されません。

image.png|500

異なるトランザクションまたは同じトランザクションが同じレコードを変更すると、そのレコードの undo log はバージョンチェーンを生成し、チェーンの先頭は最新の古いレコードであり、チェーンの末尾は最も古い古いレコードです。

実装原理 - readView#

各トランザクションがデータを読み取る際に生成される readView は異なります。

image.png|500

readView バージョンチェーンアクセスルール

  1. まず現在のトランザクション trx_id が creator_trx_id と等しいかどうかを確認し、等しければアクセスします。そうでなければ 2 へ。
  2. 現在のトランザクション trx_id が min_trx_id と max_trx_id(最大 trx_id + 1)の間にあり、すでにアクティブでない(コミット済み)かどうかを確認し、そうであればアクセスします。そうでなければ 3 へ。
  3. min_trx_id よりも小さい最大のバージョン(最も古いコミット済みバージョン)を見つけます。

image.png|500

Read Committed

トランザクション 5 の最初のスナップショット読み取りで、trx_id = 2 のバージョンが条件 2 を満たし、trx_id < min_trx_id = 3 であり、トランザクション 2 がコミットされたことを実現します。

トランザクション 5 の 2 回目のスナップショット読み取りで、trx_id = 3 のバージョンが条件 2 を満たし、trx_id < min_trx_id = 4 であり、トランザクション 3 がコミットされたことを実現します。

image.png|500

Repeatable Read

RR トランザクションの隔離レベルは、最初のスナップショット読み取りを実行したときにのみ readView を生成し、その後はその readView を再利用します。

image.png|500

この記事は Mix Space によって xLog に同期更新されました。元のリンクは https://blog.0xling.cyou/posts/mysql/mysql-2

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。