MySQL の ALTER TABLE によるスキーマ変更
テーブル設計は最初に完璧なものを作れることのほうが稀で、運用中にスキーマを変更する場面は必ず訪れます。MySQL では ALTER TABLE 文を使ってスキーマを変更しますが、本番環境での実行にはリスクが伴うため、慎重な計画と手順が求められます。
ALTER TABLE の基本操作
-- カラムの追加
ALTER TABLE users ADD COLUMN phone VARCHAR(20) DEFAULT NULL;
-- カラムの型変更
ALTER TABLE users MODIFY COLUMN phone VARCHAR(30) NOT NULL DEFAULT '';
-- カラム名と型の同時変更
ALTER TABLE users CHANGE COLUMN phone mobile_phone VARCHAR(30) NOT NULL DEFAULT '';
-- カラムの削除
ALTER TABLE users DROP COLUMN mobile_phone;
-- インデックスの追加
ALTER TABLE users ADD INDEX idx_email (email);
-- インデックスの削除
ALTER TABLE users DROP INDEX idx_email;オンライン DDL
MySQL 5.6 以降では、多くの ALTER TABLE 操作がオンライン DDL として実行でき、テーブルロックなしで変更を適用できるようになりました。
テーブルの再構築を行わず、メタデータやインデックスの変更だけで済む操作に使われます。カラム名の変更やインデックスの追加がこれに該当します。テーブルロックは最小限で済みます。
テーブル全体のコピーが必要な操作に使われます。カラムの型変更やキャラクタセットの変更などがこれに該当します。実行中はテーブルサイズに応じた時間とディスク容量が必要になります。
-- アルゴリズムの明示指定
ALTER TABLE users ADD COLUMN age TINYINT, ALGORITHM=INPLACE, LOCK=NONE;
-- COPY が必要な操作で INPLACE を指定するとエラーになる
ALTER TABLE users MODIFY COLUMN name TEXT, ALGORITHM=INPLACE;
-- ERROR: ALGORITHM=INPLACE is not supported.大規模テーブルでの注意点
数千万〜数億行のテーブルに ALTER TABLE を実行する場合、COPY アルゴリズムが走ると数時間単位の処理時間がかかることがあります。
Percona が提供するツールで、元テーブルのコピーを作成してトリガーで差分を同期しながらスキーマ変更を行います。本番稼働中でもロックなしで大規模な変更が可能です。
GitHub が開発したツールで、バイナリログを利用して差分を追跡します。トリガーを使わないため、トリガーが既に存在するテーブルでも使えるという利点があります。
これらのツールは大規模サービスでの本番スキーマ変更のデファクトスタンダードになっています。
マイグレーション管理
スキーマ変更をチームで安全に運用するには、マイグレーションツールを使ってバージョン管理するのが基本です。
-- Laravel のマイグレーション例
-- database/migrations/2024_06_01_add_phone_to_users.php
-- Schema::table('users', function (Blueprint $table) {
-- $table->string('phone', 20)->nullable()->after('email');
-- });マイグレーションファイルをコードリポジトリで管理することで、誰がいつどんな変更を行ったかが追跡でき、環境間のスキーマ差異も防げます。
安全な変更の手順
ステージング環境でテスト実行する
実行時間とロックの影響を見積もる
バックアップを取得してから本番実行する
変更後にアプリケーションの動作を確認する
やってはいけないこと
ALTER TABLE は強力なコマンドですが、本番環境では「実行する」こと自体がリスクです。事前の検証、影響範囲の把握、ロールバック手順の準備を徹底することで、安全なスキーマ変更が実現できます。



