LoginSignup
27
16

More than 5 years have passed since last update.

中途半端なマイグレーション

Posted at

Railsで使うデータベースはマイグレーションで組み立てていきますが、状況によってはマイグレーションに失敗して、マイグレーション前でもマイグレーション後でもない闇に落ちていってしまうことがあります。

MySQLの特性

マイグレーションの実行に失敗した場合、Railsは今までにした操作をロールバックして、マイグレーション前の状態に戻ろうとします。これはPostgreSQLやSQLiteの場合なら無事ロールバックできるのですが、MySQLの場合、CREATE TABLEALTER TABLEを実行すると強制的にトランザクション外となってしまうため、成功した操作をロールバックすることもできず、中途半端な状態のDBができあがってしまいます。

失敗例

マイグレーションに失敗する例としては、

  • 列名の間違い(すでにある列を追加しようとした、ない列を削除しようとした、ない列にインデックスを張ろうとしたなど)
  • すでにあるものと同名のテーブルやインデックスを追加しようとした
  • 単純な書き間違い1

などミスが大半ですが、人間はミスをするものである以上、根絶することは難しいです。

予防策

予防策としてはいくつか考えられますが、副作用もあります。

  • そもそもMySQLではなく、DDLもロールバックできるDBエンジンを使う(これだけで選ぶほど大きな問題ではない)
  • 1つのマイグレーションで1つの書き換えだけ行なって、中途半端な状態を作らせない(マイグレーションが増える)
  • 先にテスト環境でマイグレーションを流して、ちゃんと通ってから開発・本番などに持っていく

脱出方法

では、不幸にしてマイグレーションの狭間に落ちてしまった場合は、どうすればいいのでしょうか。この場合、状況としては

  • マイグレーションの進捗状況の記録(schema_migrations)…前のマイグレーションまで実行
  • DBの状態…最新のマイグレーションの途中

ということになっています。手法としては、以下のいくつかが考えられます。

  1. DBを直接叩いてマイグレーション前の状態に戻して、(誤記は修正して)もう一度rake db:migrate
  2. マイグレーションファイルから成功した分以外を消しておいて、schema_migrationsに手で追加、そして残りは別のマイグレーションに回す
  3. マイグレーションファイルの中で成功した分ををコメントアウトしてrake db:migrate、終了後にコメントアウトを戻す
  4. 手作業でDBとschema_migrationsを整え、成功したことにしてしまう

個人的には、(特段の事情がなければ)1がいいかなと考えています。


  1. 一回、remove_indexdrop_indexと書いてしまって動かない、ということがありました。 

27
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
16