もともとの話は、MySQL5.6で巨大テーブルのALTER TABLE中に
tmpdirに何かI/Oがあるせいで遅くなってる、という話で、
⇒MySQLでデータ領域をシステムと別diskにするならtmpdirも設定した方がいい - 酒日記 はてな支店
というか、でも、
During an online DDL operation that copies the table, files are written to the temporary directory. ow.ly/kmDJ1 って書いてあったけど待ちます!
— SH2さん (@sh2nd) 2013年4月24日
Σ(゚д゚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 件のコメント :
コメントを投稿