見出し画像

MySQL InnoDBの概要

「詳解MySQL 5.7 止まらぬ進化に乗り遅れないためのテクニカルガイド」を読み、MySQL5.7におけるInnoDBの概要について学んだので整理する。

InnoDBとは

MySQLのデフォルトのストレージエンジンのことで、高い信頼性とパフォーマンスを有する。
ストレージエンジンとはSQL処理を操作するMySQLのコンポーネントで、MyISAMやMemoryなどいくつか種類があるが、特別なユースケースを除いて基本的にはInnoDBを使うことを推奨されている。

InnoDB は、高い信頼性と高いパフォーマンスとのバランスをとる汎用のストレージエンジンです。 MySQL 8.0 では、InnoDB がデフォルトの MySQL ストレージエンジンです。 別のデフォルトのストレージエンジンを構成していないかぎり、ENGINE= 句を指定せずに CREATE TABLE ステートメントを発行すると、InnoDB テーブルが作成されます。

https://dev.mysql.com/doc/refman/8.0/ja/innodb-introduction.html

トランザクションを実現するInnoDBのコンポーネント

トランザクションに必要なコンポーネントとしては、テーブルスペース、バッファプール、ログ、ログバッファがある。
上記はInnoDBにおける用語であり、ややこしいので一般的なトランザクションのコンポーネントで使われる用語との対応表を記す。

テーブルスペース=ステーブルデータベース
バッファプール=データベースキャッシュ
ログ=ステーブルログ
ログバッファ=ログバッファ

テーブルスペース、ログは不揮発なストレージ、つまりHDDやSSDなどの領域にあり、一度書き込まれるとディスク破損などの異常がない限り永続的にデータが保存される。
一方でバッファプール、ログバッファは揮発性メモリ、つまりシャットダウンなどによってデータが消えてしまう領域にある。

これらのコンポーネントが組み合わさって機能することで、データが消失したり異常が発生することが防がれるようになっている。

トランザクションの処理の流れ

webアプリなどのクライアントがテーブルスペースにあるデータを参照、更新する流れとして、まずはクライアントからのリクエストによってトランザクションが開始され、リクエストの応答はすべてバッファプールが担う。
バッファプールにキャッシュされているデータの中にクライアントが参照したいデータがあればそれを返せばいいし、もしなかったらテーブルスペースからデータをフェッチする。
ディスク上にあるテーブルスペースからデータをフェッチするのは、バッファプールのキャッシュ上にあるデータを取得するよりも何倍も遅く、レイテンシーの増加につながるため、まずはバッファプールのキャッシュにデータがあるか参照されるのである。
また、データを更新するリクエストの場合、まずデータの更新をバッファプール上で行い、ログバッファとステーブルログにデータを書き込んでから、最後にテーブルスペースにデータが書き込まれるという流れになる。
この流れで更新を行うことでデータの整合性が保証されるようになっている。
このテーブルスペースにデータを書き込んで永続化することをCommitという。

データの復元について

バッファプールからテーブルスペースにデータを書き込むが、テーブルスペースに書き込まれていないバッファプープールにまだ残ったデータのことをダーティなデータという。
ダーティなデータがまだあるのにDBが落ちてしまったらデータ損失に繋がり大変なことになるが、Commit前にダーティなデータはログバッファを通じてステーブルログに保存されているので、この保存されたデータを再生することでデータが復元される。

チェックポイントについて

ダーティなページがテーブルスペースへどこまで書き込んだかを記録するのがチェックポイントである。
チェックポイントが完了しているステーブルログは、すでにテーブルスペースに存在していることを表すので、これらは消去され、スペースを解放できるようになっている。

REDOログについて

REDOログ=InnoDBエンジンが出力するInnoDBログのこと。
データに何らかの操作をするたびにREDOログが生成され、MTR(ミニトランザクション)という単位で記録されるようになっている。
このREDOログのデータはログバッファを通じてステーブルログに書き込まれており、クラッシュリカバリ(予期しないMySQLサーバーの終了からリカバリする)の際にはステーブルログに書き込まれたREDOログのMTRをテーブルスペースに対して連続的に再生し、データを時系列に沿って再現できるようになる。

UNDOログについて

データを更新する際、過去のバージョンのデータを保存しておく領域のこと。
UNDOログに保存されたデータはUNDOレコードといい、トランザクションをロールバックする時にUNDOログを使用する。
また、例えばとある行データaの更新を行うトランザクションAが実行中であり、別のトランザクションBが同じく行データaを参照したい場合、トランザクションBに対して過去のデータ(UNDOレコード)を見せることで、トランザクションに一貫したデータを参照させるMVCC(Multi Version Concurrency Control)にも使用される。

トランザクション分離レベルについて

データベースシステムでトランザクションがどのように実行されるか、特に同時に実行されるトランザクション間でデータの一貫性をどのように保つかを定義する。

トランザクション分離レベル (トランザクションぶんりレベル)または 分離レベル (英: Isolation) とは、データベース管理システム上での一括処理(トランザクション)が複数同時に行われた場合に、どれほどの一貫性、正確性で実行するかを4段階で定義したものである。隔離レベル 、 独立性レベルとも呼ばれる。トランザクションを定義づけるACID特性のうち,I(Isolation; 分離性, 独立性)に関する概念である。

https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E5%88%86%E9%9B%A2%E3%83%AC%E3%83%99%E3%83%AB

多くのデータベース管理システムでは、以下の4つの基本的な分離レベルが提供されている。

READ UNCOMMITTED

このレベルでは、一つのトランザクションがまだ完了(コミット)していないデータを、他のトランザクションが読み取ることができます。「ダーティリード」とも呼ばれます。つまり、他のトランザクションによって変更されたがまだ確定していないデータを見ることができるため、データの一貫性は保証されません。

  • 利点: 高い並行性と速度。

  • 欠点: 変更が後になって取り消された場合、不正確なデータを読み取る可能性があります。

READ COMMITTED

このレベルは、他のトランザクションによってコミットされたデータのみを読み取ることができるようにします。つまり、データを読み取る時点で、他のトランザクションによって確定された変更のみが見えます。

  • 利点: ダーティリードを防ぎます。

  • 欠点: 非連続的な読み取り(ファントムリード)の問題が発生する可能性があります。

REPEATABLE READ

このレベルでは、トランザクションが読み取ったデータは、そのトランザクションが完了するまで他のトランザクションによって変更されないことが保証されます。これにより、同じデータをトランザクション内で複数回読み取った場合、常に同じデータが返されます。

  • 利点: 繰り返し読み取りの一貫性が保証されます。

  • 欠点: 他のトランザクションが長時間ブロックされる可能性があります。また、新しい行が挿入される「ファントムリード」は防げません。

SERIALIZABLE

これは最も厳格な分離レベルで、トランザクションがデータを読み取ったり変更したりする範囲にロックをかけます。これにより、複数のトランザクションが同時に実行されている場合でも、それぞれのトランザクションが順番に実行されているかのように振る舞います。これはファントムリードを含むあらゆる種類の読み取りの問題を防ぎます。

InnoDBにおいては、REPEATABLE READとREAD COMMITTEDで上記のMVCCが用いられており、REDOログが参照される。
REPEATABLE READ、SERIALIZABLEでは過去ではなく最新のデータを読み込むようになっている。

この記事が気に入ったらサポートをしてみませんか?