Extended outer memory module
for my poor native memory.
Posts:
2022/02/13 クラビスの CTO になりました
2020/09/28 gendoc という YAML からドキュメントを生成するコマンドを作った
2020/09/13 ISUCON10 の予選を 7 位で通過した
2019/12/01 Puma の内部構造やアーキテクチャを追う
2019/05/27 Golang の正規表現ライブラリの処理の流れをざっくり掴む
2019/04/29 InnoDB の B+Tree Index について
2019/04/29 InnoDB における index page のデータ構造
2019/04/28 InnoDB はどうやってファイルにデータを保持するのか
2019/01/06 Designing Data-Intensive Applications を読んでいる
2019/01/03 年末年始に読んだ本について、など
2019/01/01 Ruby から ffi を使って Rust を呼ぶ
2018/11/10 ブラウザにおける状態の持ち方
2018/07/01 Rust で web アプリ、 或いは Rust における並列処理
2018/05/14 なぜテストを書くのか
2018/05/13 Rust で wasm 使って lifegame 書いた時のメモ
2018/03/12 qemu で raspbian のエミュレート(環境構築メモ)
2018/03/12 qemu で xv6 のエミュレート(環境構築メモ)
2018/03/03 Ruby の eval をちゃんと知る
2018/02/11 Web のコンセプト
2018/02/03 Rspec のまとめ
2018/02/03 Ruby を関数型っぽく扱う
今日は MySQL のストレージエンジンとして有名な InnoDB がデータをどうやってディスク上に保持しているのかについて。
半分くらいは翻訳記事と言えなくもない。
InnoDB は内部的に space
という仮想的なデータの単位を持つ。 これは MySQL のリファレンスとかだと tablespace
と呼ばれることもある。 space
はファイルシステム上では複数のファイルに分かれていることもあるが、論理的には一つのファイルとして扱われる。
space
は 32-bit integer の ID を持つ。
InnoDB は必ず system space
と呼ばれる space
を持っており、これは ID 0 で表現される。
MySQL では一つのテーブルが一つの space
を持つという構造になっている。(だから多分 InnoDB をストレージエンジンにしていると、テーブルは使える ID の個数に対応して 16383(=16384 - 1) 個くらいしか作れないんだと思う)
space
は page
という単位で構成される。
これは基本的に 16KB
のサイズを持っていて、それぞれの page
は 32-bit integer の ID を持つ(これを offset
と呼んでいる)。
なので 64 TB
までしかデータを保持することができない(16KB * 32-bit)。
実際には space
という論理的な単位だとサイズが不定で色々と都合が悪い。そこで space
と page
の中間単位として extent
というものがある。(extent
はデフォルトで page
が 64 個分、つまり 1 MB になっている)
すごくざっくりと説明すると space
の内部構造は、 extent
が 256 個ごとにその先頭 page
にメタ情報を保持するヘッダ page
がやってくる、という連続的な構造になっている。ただし space
の 0 番目の page
のみ space
全体に対するメタ情報も持つ。
このメタ情報を持つ page
のうち、 space
の先頭のものを FSP_HDR
(file space header) と呼び、それに続く 256 の extent
の先頭のものを XDES
(extent descriptor) と呼ぶ。
FSP_HDR
と XDES
の次には必ず IBUF_BITMAP
と呼ばれる insert buffering に関わる page
が置かれる。
また FSP_HDR
に続く IBUF_BITMAP
の後には INODE
と呼ばれる index に関わる page
が置かれる。
以下、 system space
と per-table space
の場合に分けて詳しく見ていく。
先頭の FSP_HDR
, IBUF_BITMAP
, INODE
page に続いて以下の type を持つ page が置かれる。
また 64 - 127 番目と 128 - 191 番目の page には double write buffer に使われる。
先頭の 3 つの page に続いて定義順に index の root の page が配置される。つまり 4 番目 の page にクラスタインデックスの root が来ることになる。
page
はそれぞれ FIL Header
, FIL Trailer
と呼ばれる 38 byte のヘッダと 8 byte のトレイラを持つ。残りは肝心の中身。
page
自体のメタ情報はヘッダで持つ。 page
はテーブルデータあるいは index だけでなく undo log や blob, data dictionary, トランザクションなどの用途で用いられるため。system space
の 0
番ページ以外では使っていない値。システム全体として一番最後に flush まで行なった LSN を保持する。