スマートバンク新春エンジニア駅伝2026 の第十走者の toshimaru です。
ちょうど折り返しも過ぎ、復路に突入。今日も走っていきます。
DBスキーマ変更をオンラインでダウンタイムなく安全に行いたくないですか? 私は行いたいです。では、やりましょう。
オンラインスキーマ変更ツールの利用について
オンラインスキーマ変更というと、pt-osc, gh-ost などのOSC(Online Schema Change)系のツールが有名でしょう。一方、多くのRailsユーザーは標準マイグレーション機能やridgepoleのようなツールを利用してデータベースの変更を管理していると思います。
これらのマイグレーションツールに加えて、さらにツールを導入し運用することは運用負荷が高くなりそうです。ここは、Rails界隈で一般的なマイグレーションの仕組みに乗っかる形でスキーマ変更を行いたいところです。
Rails で安全にスキーマ変更を行うための仕組みを考える
RailsでDBマイグレーションを安全に行うための仕組みというと、strong_migrations が有名でしょう。私たちも危険なマイグレーションを検知するためにstrong_migrationsを利用しています、いえ、利用していました。
なぜ過去形かというと、現在スマートバンク社のRailsマイグレーションは ridgepole を使った宣言的スキーマ管理に移行しており、strong_migrations をそのままの形では利用できないためです。
なぜ標準マイグレーションからridgepoleに移行したのかは、以下の記事をご覧ください。
上記事でも紹介している通り、ridgepole でスキーマの変更を検知した場合、 PRコメントにて DDL とともに注意文言を表示するようにしています。

しかし障害に… どうする!?
しかし、DDL の確認だけでは不十分でした。
開発者の加えた変更による DDL によって、思わぬメタデータロックが発生したり、ALTERアルゴリズム(※私たちのDBはmysqlです)が採用されたりするケースがあり、その結果、DB起因の小さな障害が発生するようになりました。
具体的にはメタデータロックによって後続のクエリがブロックされ、一部のリクエストが失敗してしまう事象が発生していました。
この問題を解決すべく、現在、以下の3つの対策を加えています。
- DDLアルゴリズム検知
- タイムアウト設定
- 外部キーチェック無効化
それぞれ見ていきましょう。
DDLアルゴリズム検知
全体の流れ
意図せぬDDLアルゴリズムが採用されてしまうのを防ぐため、事前にCIでアルゴリズムを検知して警告する仕組みを構築しました。全体の検知の流れとしては以下の通りです。

CI上のチェックスクリプト
CI上の擬似チェックスクリプトとは以下のようになっております。
- CIは GitHub Actions で実行
/bin/ridgepoleは ridgepole 実行をラップしたスクリプト$GITHUB_OUTPUTを後続の処理でハンドリングする
echo "### Testing ALGORITHM=INSTANT" if ./bin/ridgepole apply --alter-extra "ALGORITHM=INSTANT"; then echo "algorithm_level=instant" >> $GITHUB_OUTPUT else echo "### INSTANT failed, testing ALGORITHM=INPLACE" if ./bin/ridgepole apply --alter-extra "ALGORITHM=INPLACE"; then echo "algorithm_level=inplace" >> $GITHUB_OUTPUT else echo "algorithm_level=copy" >> $GITHUB_OUTPUT fi fi
危険度に応じたコメント
採用されるDDLアルゴリズムの危険度に応じて、以下の3つの信号灯を灯すようにしました。
| 危険度 | アルゴリズム | 挙動の概要 | 主な操作 |
|---|---|---|---|
| 🟢 低 | INSTANT |
ロックなし、瞬時完了 | カラム追加、リネーム |
| 🟡 中 | INPLACE |
DML許可、リソース消費大 | インデックス追加 |
| 🔴 高 | COPY |
DML禁止、テーブルコピー | 型変更、主キー変更 |
それぞれの危険度に応じて、その危険性の説明と推奨される対応を併記するようにしました。



タイムアウト設定
上述した strong_migrations gem の利用時は lock_wait_timeout 値が 10秒に設定されていました。
# Set timeouts for migrations StrongMigrations.lock_timeout = 10.seconds
しかし、ridgepole化に伴い strong_migrations gem が使えなくなったことにより、lock_wait_timeout は MySQL のデフォルト値が使われることになりました。
ここで驚くべきことですが、MySQL のデフォルトだとlock_wait_timeout 値は1年間(!)となっています。ほぼタイムアウトしないと言って差し支えない設定値なので、この値はDDL実行時は適切な値を設定しておくべきでしょう。
SHOW VARIABLES LIKE 'lock_wait_timeout'; +-------------------+----------+ | Variable_name | Value | +-------------------+----------+ | lock_wait_timeout | 31536000 | +-------------------+----------+ 1 row in set (0.010 sec)
ということで、 ridgepole に下記のオプションを加えています。
$ bin/ridgepole --pre-query "SET SESSION lock_wait_timeout=5"
この設定により、メタデータロックの待機時間が lock_wait_timeout 秒を超えた場合に DDL をタイムアウトさせられるため、より安全にスキーマ変更を実施することができます。
外部キーチェック無効化
私たちのRailsプロジェクトでは、外部キー制約を利用しています。MySQL のデフォルト設定(foreign_key_checks=1)では、外部キー制約の追加は COPY アルゴリズムが採用されます。
外部キー制約の追加
INPLACE アルゴリズムは、
foreign_key_checksが無効な場合にサポートされます。 それ以外の場合は、COPY アルゴリズムのみがサポートされます。
ref. MySQL :: MySQL 8.0 リファレンスマニュアル :: 15.12.1 オンライン DDL 操作
上述した通り、COPY アルゴリズムでの外部キー制約追加は、危険なオペレーションとなりえます。INPLACE アルゴリズムで外部キー制約追加が実行されるよう、ridgepole 実行時に一時的な外部キーチェック無効化オプションを加えています。
$ bin/ridgepole --pre-query "SET SESSION foreign_key_checks=0"
foreign_key_checksを無効化することで、外部キー制約違反となる値が混入するリスクがありますが、そこはアプリケーション側でデータの整合性を担保してもらうことにしています。
まとめ
Railsのマイグレーション機構に乗りつつ、オンラインスキーマ変更を安全に行うために、以下の3つの対策を導入しました。
- DDLアルゴリズム検知 - CIで
INSTANT→INPLACE→COPYの順にテストし、危険度を可視化 lock_wait_timeoutの設定 - MySQLデフォルトの1年から3秒に短縮し、メタデータロックによる障害を防止- 外部キーチェックの無効化 - 外部キー追加時に
COPYではなくINPLACEアルゴリズムが採用されるように
これらの仕組みにより、開発者はPR上で事前にDDLの実行リスクを把握できるようになりました。実際、この仕組みを導入後、DBマイグレーションは数多く実施されていますが、今のところ大きな障害はありません。
pt-oscなどの外部ツールを導入せずとも、CIでの事前検知とMySQLのセッション設定を組み合わせることで、十分に安全なオンラインスキーマ変更が実現できました。
めでたしめでたし。
参考記事
- https://developers.freee.co.jp/entry/introduction-of-pt-online-schema-change
- https://made.livesense.co.jp/entry/2025/06/26/080000
- https://moneyforward-dev.jp/entry/2022/10/13/suggestion-strong-migrations-gem/
- https://techracho.bpsinc.jp/hachi8833/2025_07_16/151486
- https://dev.mysql.com/doc/refman/8.0/ja/innodb-online-ddl-operations.html
- https://gihyo.jp/article/2022/09/mysql-rcn0180
次のスマートバンク新春エンジニア駅伝2026走者は、stefafafan さんです!