InnoDBのオンラインDDLとtmpdirの罠

ちょっと大きなサイズのテーブルをALTER TABLE中に以下のようなエラーが発生しました。

ERROR 1034 (HY000) at line 38: Incorrect key file for table 'table'; try to repair it

やばっ、テーブル壊れた!?って思ったんですけどテーブルは壊れてませんでした。もう一度リトライしても同じエラーが。。。

なんだこれって思ったので調べてみることに。

オンラインDDLでは一時ファイルがtmpdirに作成される

ALTER TABLEした時は元のテーブルと同じ場所にテーブルのコピーが作成され、コピー完了後に一気に置き換えられるって思っていたのですが、オンラインDDL中はどうも具合が違うようです。

ほとんどの場合、ALTER TABLE は元のテーブルの一時コピーを元のテーブルと同じディレクトリに作成します。ただし、ALTER TABLE でインプレース手法 (オンライン DDL) が使用された場合、InnoDB は一時ファイルを一時ファイルディレクトリに作成します。このディレクトリがそのようなファイルを保持するほどに十分に大きくない場合は、tmpdir システム変数に別のディレクトリを設定する必要があることがあります。オンライン DDL については、「InnoDB とオンライン DDL」を参照してください。

引用元:MySQL 5.6 マニュアル : B.5.4.4. MySQL が一時ファイルを格納する場所

おお、なるほど!そういうことだったのか。

今回のエラーが発生したサーバーはdatadir(データファイル格納ディレクトリ)とtmpdir(一時ファイル格納ディレクトリ)を別々のパーティションで指定していました。

しかしtmpdirで指定していたパーティションの空き容量が少なく、ALTER TABLEで作成される一時ファイルの必要サイズに足りなかったためエラーになっていたようです。

解決方法1:tmpdirを変更する

my.cnfの設定のtmpdirを容量に余裕の有るパーティションのディレクトリを指定するように変更してあげることで解決します。

[mysqld]
tmpdir = /tmp

解決方法2:ALTER TABLEにALGORITHM=COPYを指定する

my.cnfを編集してサーバーを再起動したく無いっていうときは、ALTER TABLEにALGORITHM=COPYを指定して実行すればtmpdirを使用せずに元テーブルと同じ場所にコピーを作ってくれるようになるので、これで対応出来ます。

ALTER TABLE `table` ADD column1 int, ALGORITHM=COPY;

システム変数old_alter_tableを有効にすることでも対応可能です。

SET GLOBAL old_alter_table = 1;

元に戻しておかないと今後オンラインDDLの恩恵を受けれなくなってしまいますので忘れずに。

SET GLOBAL old_alter_table = 0;

まとめ

ALGORITHM=COPYでその場しのぎは出来ますが、オンラインDDLじゃなくなりますので、本質的に解決したけりゃtmpdirのパスを変更しましょう。

・・・はい、変更します。

コメントを残す