MySQL InnoDB Internals

最終更新: 2022-08-14 15:11:43 +0800 +0800
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

InnoDB はテーブルデータとインデックスを、テーブルスペースに編成されたページへ保存します。 テーブルスペースのページサイズは固定で、データディレクトリの初期化時に選択されます。既定のページサイズは 16 KiB です。 ページ指向 I/O により、インデックス局所性、バッファープール容量、行幅がクエリコストに影響する理由を説明できます。

データディクショナリとメタデータ #

MySQL 8 はトランザクション型データディクショナリを InnoDB に保存します。そのためスキーマ、テーブル、列、インデックス、 ストアドプログラム、権限を含むサーバーメタデータはクラッシュセーフであり、アトミックなデータ定義操作に参加します。 アプリケーションはメタデータを調べるために INFORMATION_SCHEMA、Performance Schema、または SHOW 文を使う必要があります。 内部ディクショナリテーブルはアプリケーションインターフェースではありません。

INFORMATION_SCHEMA はメタデータに対する SQL ビューを公開します。sys スキーマは Performance Schema と Information Schema のデータに、 コストの高いステートメントや未使用インデックスなど、人間向けのビューを追加します。

データ定義操作がアトミック DDL に対応している場合、ディクショナリメタデータとストレージエンジン状態を 1 つのアトミック DDL トランザクションとして更新します。 ディクショナリレコードはサーバー内部にとどまり、基盤の InnoDB テーブルを直接読み書きすることはサポートされません。

テーブルスペース #

InnoDB のインストールでは次を使用できます。

  • システムテーブルスペース(変更バッファーデータとその他の共有 InnoDB 構造用)。
  • innodb_file_per_table を有効にしたとき InnoDB テーブルごとに作成される file-per-table テーブルスペース。
  • 管理者が作成し、互換性のあるテーブルへ割り当てる 一般テーブルスペース。
  • InnoDB が管理する独立した undo テーブルスペースと一時テーブルスペース。

すべての構成で、1 テーブルが 1 つのオペレーティングシステムファイルに安全に対応するわけではありません。 一貫したデータベースはデータファイル、redo ログ、メタデータにまたがるため、バックアップと復元には MySQL 対応ツールまたは文書化された物理バックアップ手順を使います。

ページ、エクステント、インデックスレコード #

テーブルスペースはページに分割され、ページはエクステントにまとめられます。既定の 16 KiB ページサイズでは、 1 エクステントは 64 ページを含み、1 MiB を占有します。InnoDB は小さいセグメントをページ単位で割り当て、 成長するとエクステント全体を使用します。

各テーブルはクラスタ化インデックスを中心に編成されます。クラスタ化インデックスのリーフページには行レコードが含まれ、 内部ページには区切りキーと子ページへのポインターが含まれます。セカンダリインデックスのリーフレコードにはセカンダリキーと、 クラスタ化レコードを見つけるための主キーが含まれます。undo ページは MVCC に必要な古い行バージョンを保持し、 内部一時テーブルは種類とリリースに応じてグローバル一時テーブルスペースまたはセッション一時テーブルスペースを使用できます。

ダブルライトバッファーとリカバリー #

InnoDB は最終的なテーブルスペース書き込みの前に、ダブルライト機構を通してダーティページを書き込みます。 そうしなければストレージ障害によって部分的に書き込まれたページ、つまり torn page が残る可能性があります。 リカバリー中、ページチェックサムが最終書き込みの破損を識別すると、InnoDB は有効なダブルライトコピーを使えます。

redo ロギングは影響を受けるページがフラッシュされる前に変更を記録します。クラッシュリカバリー中、InnoDB は必要な redo を再生し、 undo レコードで未完了トランザクションをロールバックします。耐久性設定を無効にすると確認済み書き込みの意味が変わるため、 性能だけのチューニングではなくデータ損失に関する判断として扱う必要があります。

検査 #

ファイルを調べるのではなく、サポートされるスキーマを使います。

sql
SELECT name, space_type
FROM information_schema.innodb_tablespaces
ORDER BY name;

SELECT pool_id, pool_size, free_buffers, database_pages
FROM information_schema.innodb_buffer_pool_stats;

SELECT event_name, count_star, sum_timer_wait
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE event_name LIKE 'wait/io/file/innodb/%';

INFORMATION_SCHEMA.INNODB_* テーブルは論理的な InnoDB オブジェクトとバッファー状態を記述します。 Performance Schema は観測された処理と待機を属性化します。どちらのインターフェースもリリースごとに変化するため、 運用クエリはデプロイ済み MySQL のバージョンを対象にする必要があります。

参考資料 #

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)