LoginSignup
1

More than 5 years have passed since last update.

中間のmigrationをもう一回実行させ方

Posted at

環境

Amazon Linux

# rake about
sinatra                   1.4.7
ruby                      2.3.1p112 
Environment               staging
Database adapter          mysql2
Database schema version   201610xxxxxxxxx

背景

ステージング環境は複数のメンバーが弄ってます。いつの間に、migrationはこんな感じなってしまった。

# RACK_ENV=staging bundle exec rake db:migrate:status
database: xxx_staging

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20160826080803  Create xxx
   up     20160929044948  Create xxx
   up     20160929045000  Create xxx
   up     20160929045041  Create xxx
   up     20161111073930  A(add column is_prime)
   up     20161116033102  B
   up     20161116105100  C

確かに全部migration全部実行されているように見えますが、確認してみたら、[A]は実行されてないようです。以下のエラーが出た。

 ActiveModel::UnknownAttributeError - unknown attribute 'is_prime' for table_a

すぐdb/structure.sqlファイルを確認したら、table_aにis_primeはなかった。つまり、中間のmigration(A)を実行されてない

対策

やり直す

もちろん、DBを消して、全てのmigrationをやり直すのは一番速いんですが、データをエクスポートして、インポートしないといけなくて、ちょっと面倒ですし、後発生する可能せが低いですが、もし本番そういうことが起きたら、どう対応すべきかな。

mysqldump -uroot db_name > dump.sql
RACK_ENV=staging bundle exec rake db:drop && RACK_ENV=staging bundle exec rake db:create && RACK_ENV=staging bundle exec rake db:migrate  
mysql -uroot db_name < dump.sql

別の方法

そのmigrationだけ実行させてみた

RACK_ENV=staging bundle exec rake db:migrate:redo VERSION=20161111073930

したら、以下のエラーが出た。

Mysql2::Error: Can't drop 'is_prime'; check that column/key exist:

つまり、redoは[down & up]という実装になってます。

ロールバックしてた

RACK_ENV=staging bundle exec rake db:rollback STEP=4

↑と同じエラーが出た。

Mysql2::Error: Can't drop 'is_prime'; check that column/key exist:

一歩づつにやると[A]まではできて、こんな感じになります。

# RACK_ENV=staging bundle exec rake db:migrate:status
database: xxx_staging

 Status   Migration ID    Migration Name
--------------------------------------------------
   up       20160826080803  Create xxx
   up       20160929044948  Create xxx
   up       20160929045000  Create xxx
   up       20160929045041  Create xxx
   up       20161111073930  A(add column is_prime)
   down     20161116033102  B
   down     20161116105100  C

まあ、そうだね!そもそも今is_primeは存在してないですから。

migrationファイルを外してみた

migrationはdb/migrationの下のファイルを順番実行するはずだ。だが、二回ロールバックして、20161111073930_xx_xx.rbを外して、migrationを実行して、その後、20161111073930_xx_xx.rbを戻して、実行したら、うまくいけるじゃないと思ったが、何も変わらなかった。

でも、db/migrationのしたのmigrationファイルを実行されたかどうかというの記録きっと別の所にあるということが分かった。ファイル名だけって決めることじゃない。

migrationテーブル修正

mysql> use auction_staging;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_auction_staging |
+---------------------------+
| ar_internal_metadata      |
| xxx_results               |
| xxx                       |
| schema_migrations         |
|        ....               |
+---------------------------+
11 rows in set (0.00 sec)

mysql> select * from schema_migrations;
+----------------+
| version        |
+----------------+
| 20160826080803 |
| 20160929044948 |
| 20160929045000 |
| 20160929045041 |
| 20161111073930 |
| 20161116033102 |
| 20161116105100 |
+----------------+
12 rows in set (0.00 sec)

なるほど、20161111073930というrowを消せた、きっとロールバックができるはず!

select * from schema_migrations where version = '20161111073930';
delete   from schema_migrations where version = '20161111073930';

二回ロールバックして、migrationしたら、直しました! :smiley:

RACK_ENV=staging bundle exec rake db:rollback STEP=2
RACK_ENV=staging bundle exec rake db:migration

最後

@jhoshina 色々アドバイスしていただき、ありがとうございます!助かりました!

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
1