YakstYakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。TABLEによるテーブル変更の進捗状況を確認するには、いくつかの方法がある。それぞれの方法と利点、欠点を紹介する。TABLEの進捗状況を確認する方法について顧客から尋ねられた。5.5以前は、テーブルに対するALTERの実行状況を本番環境で確認するのは少々難しく、(数百万行もあるような)巨大なテーブルではなおさらだった。これは、リビルドとテーブルのロックを伴うため、パフォーマンス低下だけでなくユーザ影響もあったためだ。いえ、ALTERを始めてしまえば、それがいつ終わるのかを知るのはとても重要なことだ。TABLE中もテーブルはリビルドされないが、テーブルへのロックはかかってしまう。5.5以降で使用可能。DDL」機能が登場した。これにより、テーブルが変更されている間でもSELECTやINSERT、UPDATE、DELETEといった文を実行できるようになった。最新バージョンでは、ファイルのコピーとロックを、それぞれALGORITHMとLOCKオプションで制御することも可能だ。5.6ではまだ、カラムのADDやDROP、データタイプの変更、プライマリキーのADDやDROPについてはテーブルのリビルドが必要だ。詳しくは以下のページの表を参照しよう。TABLEの進捗状況を確認できる。Toolkitのpt-online-schema-changeを使うことだ。TABLEを実行している間、データの変更(INSERT、UPDATE、DELETE)はどうなっているの?」という質問を何度もされた。ここでその質問への答えを簡単に説明しよう。pt_osc_nil_nil_test_upd.TRN元のテーブルに対する更新を新しいテーブル(*_nil_test_new)の行に対しても行うために、トリガ(拡張子TRGのファイルと、INSERT、UPDATE、DELETEごとの拡張子TRNのファイル)が作られていることがわかる。コピー中に元のテーブルに発生した変更は、新しいテーブルにも適用される。このツールは既にテーブルにトリガが定義されていると正常に動作しない。5.6からデフォルトでONだ)。TABLEを始めると、InnoDBは#sql-1c80_27.ibdのような、#sqlから始まり拡張子が.ibdのランダムな名前の一時表領域ファイルを、データディレクトリ内に作成する。#sql-1c80_27.ibdテーブルを変更している間、InnoDBはnil_test.ibdのようなibdファイルを読み込み、新しいページを#sql-1c80_27.ibdの方に書き込んでいく。TABLEの進捗状況が確認できる。10doneALTERを実行している時にこのスクリプトをデータディレクトリで実行すると、以下のように進捗がわかる。protected]:/var/lib/mysql/nil#このスクリプトを使うにあたって考える必要があるところがいくつか存在する。$TABLENAME変数を必要に応じて変更する必要がある。TABLEでしか動かない。データディレクトリで実行しなければならない(例として/var/lib/mysql/nil)実際の新しいテーブルはファイルサイズとは微妙に一致しないので、コマンドの結果は概算でしかない。削除された行やフラグメントのサイズは計算結果に影響してくる。TABLEの進捗状況確認はできないということをここで言っておきたい。fast_index_creationは、セカンダリインデックスが一切ない状態でテーブルをまず作成し、データがロードされてからセカンダリインデックスを作成する。セカンダリインデックスの作成中は一時表領域(.ibdファイル)は存在しない。このプロセスは非常に興味深いので、ここで少し説明しよう。「fast_index_creation」でセカンダリインデックスを追加する時には、テーブル定義を更新するために#sql***.frmは作成されるが、.ibdファイルは作成されない。ファイルソートをしてから元のテーブルの.ibdファイルにインデックスを直接作ってしまう。TABLEが終わるまでファイルサイズが増えていく。最初は以下のように、ファイルサイズは変わらない(nil_test.ibd)。#sql-671_25.frmそれから突如.ibdファイルのサイズが増えていく。protected]:/var/lib/mysql/nil#これは、1つだけセカンダリインデックスが張られている場合に起こる。複数のセカンダリインデックスがある場合、各インデックスについて処理が実行されるので、ファイルサイズの増加と一時停止が複数回、すなわちセカンダリインデックスの回数分だけ起きることになる。TABLEの実行中、information_schemaのGLOBAL_TEMPORARY_TABLESを見ることで、テンポラリテーブルに挿入されたレコードの数が分かる。extendedで確認することができる。Schwartzの2008年の記事MySQLのクエリの完了時間を見積もるを参照しよう。詳しく説明されている。ONでなくても使える方法だが、他に同時に実行されているトランザクションがない状態である必要がある。TABLEの進捗状況を確認するのは非常に難しい。PROCESSLIST"で確認してみたが、同じように、information_schema.processlistテーブルに対してクエリを発行しても進捗状況を確認できる。双方の出力結果は一致しないようだ。information_schema.processlistテーブルの方が、正確な進捗状況のように見える。TABLEはサーバのハングアップやクラッシュを引き起こすことがある。TABLEを本番サーバで実行する時は、しっかりと計画を立てる必要がある。MySQLはいわゆる「プログレスバー」を提供していないので、上に書いたような方法で進捗状況を確認する必要がある。ここに書いた以外にも方法をご存じのようなら、コメントで教えてくれれば、喜んで記事に追加したい。@yakstcom_req_jaYakstYakstお問い合わせ。