MySQL のストレージエンジンについて調べた
なぜか忘れたけど MySQL のストレージエンジンについて調べたので書いておく。
はじめに断っておくと MySQL 5.6 以降について書いています。
MySQL の「ストレージエンジン」とはなにか?
ストレージエンジンとはInnoDBのことである。
MySQLはプラガブルな(置き換え可能な)ストレージエンジンの仕組み(アーキテクチャ)を備えている。何も考えなければそれはInnoDBであり、通常はそのままでよい。ストレージエンジンにはそれぞれ特徴があるので、特殊な使い方(ユースケース)を求めている場合、最適なストレージエンジンが他にあるかもしれないというのを頭の片隅に覚えておきたい。
自分が使っているMySQLがサポートしているストレージエンジンを知りたい場合、SHOW ENGINESコマンドを実行する。ちなみに手元にあるMySQL 5.6.13で実行したら以下のようになった。
mysql> show engines; +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 9 rows in set (0.00 sec)
(PERFORMANCE_SCHEMAもストレージエンジンなのか...)
それぞれのストレージエンジンの特徴は MySQL :: MySQL 5.6 Reference Manual :: 15 Alternative Storage Engines に詳しく書いてある。
ストレージエンジンの種類はテーブルを作るときに指定することができる。CREATE TABLE 文の ENGINE
オプションに使いたいストレージエンジンの名前を書けばよい。例えば BLACKHOLE を使いたいならばこうなる。
CREATE TABLE t1 ( id INT NOT NULL AUTO_INCREMENT, col1 INT NOT NULL, col2 INT NOT NULL, PRIMARY KEY (id) ) ENGINE=BLACKHOLE;
既存のテーブルのストレージエンジンを変更したい場合はALTER TABLEで可能だ。たとえば MEMORY に変更したい場合はこうする。
ALTER TABLE t1 ENGINE=MEMORY;
アーキテクチャ
次にストレージエンジンのアーキテクチャを俯瞰したい。
ここで抽象ストレージエンジン I/F と書いたところは実際には以下の2つである。
- handler 抽象クラス
- handlerton 構造体
これは sql/handler.h で定義され、sql/handler.cc で一部実装されている。
ストレージエンジンではこれを実装すればよい。例えば InnoDB では以下のファイルになる。
ストレージエンジンを自作してみる
ストレージエンジンは自分で作ることができるので試してみたい。
まず実装するストレージエンジンの要件を以下のように決めた。
MySQL Internals Manual :: 22 Writing a Custom Storage Engine :: 22.2 Overview にも、まずリードオンリーのストレージエンジンから始めて、次に INSERT, UPDATE, DELTE をサポートして、その後にインデックスやトランザクションなどをサポートするのがよいみたいに書いてあった。
名前
MYCSV ストレージエンジンにした。
Example から始める
22.3 Creating Storage Engine Source Files によると EXAMPLE storage engine というのがあるので、ここから始めるのがいいらしい。
ビルドできるようになる
ファイルを作ってまずやることは以下の2つだ。
- 動かし方(ビルド方法)を知る
- ちゃんと動くか確かめる
自分のコードを書く前に「いまそこにあるコード」がちゃんと動くことを確認するのは大事なことだ。
詳細は ビルドできるようにする · Issue #1 · takatoshiono/mysql-mycsv に書いたけど、この時点で以下の状態だった。
- テーブルが作れる
- INSERT が成功する(ように見える)
- SELECT すると空っぽ
インターフェースを確認する
実装を始める前に何を実装すればいいか知る必要があるので、テーブルからデータを読み取るために必要なストレージエンジンインターフェースを確認しておく。
MySQL :: MySQL Internals Manual :: 22 Writing a Custom Storage Engine の 22.10 Implementing Basic Table Scanning までをざっと読む。
初期化フェーズ
handler クラスのインスタンスを作る。
テーブルの作成
テーブルを作るときには handler インスタンスの create メソッドが呼ばれる。これは handler 抽象クラスの以下の純粋仮想関数を実装したものだ。
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
MySQL :: MySQL Internals Manual :: 22.8 Creating Tables
テーブルのオープン
同じく open メソッドが呼ばれる。これはキャッシュされるので毎回呼ばれるわけではない(と CSV ストレージエンジンのソースコードに書いてあった)。
virtual int open(const char *name, int mode, uint test_if_locked)=0;
MySQL :: MySQL Internals Manual :: 22.9 Opening a Table
テーブルの読み取り
例えば CSV ストレージエンジン(tina という名前)で9行読むときの流れはこうなるらしい。
ha_tina::store_lock ha_tina::external_lock ha_tina::info ha_tina::rnd_init ha_tina::extra - ENUM HA_EXTRA_CACHE Cache record in HA_rrnd() ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::rnd_next ha_tina::extra - ENUM HA_EXTRA_NO_CACHE End caching of records (def) ha_tina::external_lock ha_tina::extra - ENUM HA_EXTRA_RESET Reset database to after open
MySQL :: MySQL Internals Manual :: 22.10 Implementing Basic Table Scanning
実装する
詳解MySQL という本がある。少し古い本なのだが、この本にストレージエンジンを実装するという章があるので(とても)参考にした。ソースコードをダウンロードできるので便利。
成果物がこちらです。
takatoshiono/mysql-mycsv · GitHub
実装するときに苦労した点だけ書いておく。
- 普段 Ruby でやっているような、テストを書いて確認しつつ実装するということが困難
- MySQLでもMySQL :: The MySQL Test Framework, Version 2.0 :: 7.1 Unit Testing Using TAPに書いてあるようにユニットテストは書けるようなので試してはみたけど実用までには至らなかった
- MySQL独自の関数(
my_malloc
など)を調べるのにいちいちMySQLのコードを読む必要があるので時間がかかる - コード書く〜ビルドする〜動かして試す、というサイクルに時間がかかる
参考リンク
- MySQL :: MySQL 5.6 リファレンスマニュアル :: 15 代替ストレージエンジン
- MySQL :: MySQL Internals Manual :: 22 Writing a Custom Storage Engine
- MySQL ストレージエンジン · Issue #30 · takatoshiono/memo · GitHub
- Read from file by takatoshiono · Pull Request #2 · takatoshiono/mysql-mycsv · GitHub
- 作者: Sasha Pachev,吉川英興,田中慎司,伊藤直也,菅野良二
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2007/11/20
- メディア: 大型本
- 購入: 4人 クリック: 86回
- この商品を含むブログ (23件) を見る