VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
ALTER TABLE の仕組み
MySQL のALTER TABLE には、操作とバージョンに応じて 2 つのモードがあります。
再構築 DDL(従来の動作): MySQL は新しいスキーマで新しいテーブルを作成し、すべての行をコピーし、テーブルを入れ替えて、元のテーブルを削除します。その間ずっとテーブルは書き込みに対してロックされます。大きなテーブルでは数分から数時間です。
オンライン DDL: 多くの操作は、読み取りも書き込みもブロックせずに実行できます。MySQL はその場で変更を行うか、同時 DML を許可しながらバックグラウンドでテーブルを再構築します。特定の操作がどう動くかを調べるには、ALGORITHM 句と LOCK 句を明示的に追加します。要求した制約を満たせない場合、MySQL はステートメントを拒否します。
オンライン DDL のロックモード
ALGORITHM 句と LOCK 句は、MySQL が変更をどう実行するかを制御します。
速いものと遅いもの
ALGORITHM=INSTANT(MySQL 8.0)を使う操作は、テーブルのサイズに関係なくほぼ瞬時です。
- 任意の位置への列の追加(MySQL 8.0.29 以降)
- 仮想生成列の追加/削除
- 列のデフォルト値の変更
ALGORITHM=COPY を必要とする操作は、その間ずっと書き込みをブロックします。
- 列のデータ型の変更
- 文字セットの変換
- (全文インデックスの追加はこれに含まれません。
INPLACEで実行されますが、常に少なくともLOCK=SHAREDが必要なため、読み取りは進み、書き込みはブロックされます。LOCK=NONEは ERROR 1846 で拒否されます)
ALGORITHM=INPLACE, LOCK=NONE を使います。テーブルの再構築はバックグラウンドで行われ、DML は進みます。100GB のテーブルへのインデックス追加には時間がかかりますが、アプリケーションをブロックしません。
本番環境での大きなテーブルの移行
ロックするには大きすぎるテーブルでALGORITHM=COPY を必要とする操作には、外部ツールを使います。
pt-online-schema-change(Percona Toolkit)
pt-osc はシャドウテーブルを作成し、行をバッチでコピーし、進行中の書き込みをトリガーで複製してから、テーブルを入れ替えます。アプリケーションのダウンタイムはありません。
gh-ost(GitHub)
gh-ost はトリガーの代わりにバイナリログを使うため、高い書き込み負荷の下でより信頼性があります。トラフィックの多いテーブルに選ばれるツールです。
どちらのツールも、テーブルに主キーが必要です。
マイグレーションツールとバージョン管理
スキーマ変更はバージョン管理されたマイグレーションファイルで追跡します。一般的なツールは次のとおりです。
各ツールは、どのマイグレーションが実行済みかを追跡するためにデータベース内にマイグレーションテーブルを保持するため、再実行は安全です。
よくある質問
テーブルをロックせずに列を追加できますか?
NULL 許容の列を任意の位置に追加する操作はALGORITHM=INSTANT を使い、テーブルのサイズに関係なくミリ秒で完了します(MySQL 8.0.29 以降)。そうならない場合は、ALGORITHM=INPLACE, LOCK=NONE、または pt-osc か gh-ost を使ってください。
ALTER TABLE がテーブルをロックするかどうかはどう確認しますか?
ステートメントにALGORITHM=INPLACE, LOCK=NONE を追加します。MySQL は可能ならロックせずに実行し、不可能ならエラーを返します。どちらにしても、推測なしに確定的な答えが得られます。
マイグレーションはトランザクション内で実行すべきですか?
DDL ステートメント(ALTER TABLE、CREATE INDEX、DROP TABLE)は MySQL で暗黙のコミットを引き起こし、ロールバックできません。BEGIN/COMMIT ブロックの中で実行しても保護にはなりません。トランザクションのロールバックに頼るのではなく、アプリケーションレベル(二重書き込み、フィーチャーフラグ)でロールバック戦略を計画してください。
トラブルシューティング
関連項目
- MySQL のバックアップ戦略 — 移行の前には必ずバックアップを取る
- MySQL のトランザクション — MySQL でどの移行操作がトランザクショナルか
- MySQL のテーブルパーティショニング — パーティショニングの変更もスキーマ移行
- ORM で MySQL を使う: Django、Rails、および Prisma — ORM が生成した DDL を安全に適用する