2013年4月24日水曜日

MySQL5.6 ALTER TABLE中のtmpdirのファイル

なんかうれし恥ずかし状態になっているので頑張って調べてます。

もともとの話は、MySQL5.6で巨大テーブルのALTER TABLE中に
tmpdirに何かI/Oがあるせいで遅くなってる、という話で、
MySQLでデータ領域をシステムと別diskにするならtmpdirも設定した方がいい - 酒日記 はてな支店

というか、でも、

Σ(゚д゚lll) 結論出てるじゃないですか!?


はい、調べます。

1) ALTER TABLEが走るとALGORITHM = INPLACEかどうか、INPLACEでALTER TABLEできるかどうかの判定が走る(sql/sql_table.cc:mysql_inplace_alter_table)

2) もろもろの関数を経て、InnoDBのOnline ALTER TABLEにたどりつく(storage/innobase/handler/handler0alter.cc:ha_innobase::inplace_alter_table)

3) Online ALTER TABLE用のtemporary merge fileが作られる。DDL中の更新差分をココに閉じ込めて、後からテンポラリテーブルにマージする動き。内部的にはMySQL内共通のテンポラリファイル作る関数を、ファイル名の先頭"ib"で呼んでる。(storage/innobase/row/row0log.cc:row_log_table_open)

4) DDL中の更新差分は、InnoDBのINSERT, UPDATE, DELETE用APIの中でOnline ALTER TABLE中かどうかを判定して、
   フラグが立ってたらさっきのテンポラリファイルにデータを突っ込む関数が呼ばれる(storage/innobase/row/row0ins.ccとか)


if (err == DB_SUCCESS && dict_index_is_online_ddl(index)) {
                        row_log_table_insert(rec, index, offsets);
                }

こんなかんじ。

5) ALTER TABLE中の面倒は(storage/innobase/row/row0log.cc:row_log_online_op)が見ているぽくて、

if (byte_offset + srv_sort_buf_size >= srv_online_max_size) {
                        goto write_failed;
                }

ファイルの末尾+sort_buffer_size(ソートバッファサイズごとに処理してるぽいので、
次の1回分くらいしか残りがない、という感じ?)がinnodb_online_alter_log_max_sizeに達するとエラーで抜けるようになってる。

6) ALTER TABLEの終了後に、テンポラリファイルからINSERT, UPDATE, DELETEの差分をマージする(storage/innobase/row/row0log.cc:row_log_table_apply_*)

こんな感じでしょうか。5) はちょっと自信無い…。


ざっくりですが楽しませていただきました。

ネタをくれた@fujiwaraさん、
鬼振りしてくれた@kamipoさん、@kenjiskywalkerさん、@sh2ndさん、@oranieさん、
美味しゅうございました。ありがとうございます。

0 件のコメント :

コメントを投稿