INODEVLOG

WEBアプリ開発・事業開発・ビジネスモデル・読書の情報などをお届けしています。

【Heroku】Railsで過去のマイグレーション修正&復旧する

今日は先日遭遇してしまった

「Herokuで過去のマイグレーションファイルを誤って反映されとる…orz」

という状況での修正反映&データ復旧の手順をまとめてみます。

ま、普通に開発してればあまりないシチュエーションですが…(・_・)

技術的に難しくはないもののHeroku独自の仕様もあったりしますので、

もしもやらかしちゃった方がいたら参考にしてみて下さい。

f:id:inodev:20180410003634j:plain

そもそもやりたいこと

通常マイグレーションファイルを追加して対応するが、

どうしても反映済のバグってる過去のマイグレーションファイルの内容を変更したい。

そこで今回は現在のDBのデータを退避させて、修正後に戻す作業を行う。

バックアップ&リストアの前提条件

  • pg(PostgreSQL)のアドオンを使用していること
  • 正しいデータがデプロイ環境のDBに存在していること

※そもそも間違ったDB内容のデータが投入されているのであれば、復旧用のrake task等でデータを整形してから対応するか、マイグレーションファイルにデフォルト値を記載する等の対応が必要になるでしょう…。

※下記手順をローカル開発環境、またはStaging(テスト環境)で実施してからProduction(本番環境)で行ったほうが良いでしょう。

Herokuのメンテナンスモード機能をONにする

ユーザ操作によるDB更新を抑止します。

DBの矛盾が発生しないようにHerokuの機能でメンテナンスモードでユーザーのアクセスを制限しましょう。

Settings の下にある Maintenance Mode から可能です。

f:id:inodev:20180409235226p:plain

コマンドでは

$ heroku maintenance:on --app sushi

で出来るようです。

Maintenance Mode | Heroku Dev Center

バックアップを作成する

無料でも手動バックアップの作成&リストアは可能です。

まず『利用している』DBのアドオンの詳細ページに行きましょう。

(複数DBが存在する場合もあるので注意)

f:id:inodev:20180409235506p:plain

そして Durability タブ下の Create Manual Backup を実施します。

コマンドでは

$ heroku pg:backups:capture --app [アプリ名]

で出来ます。

Heroku PGBackups | Heroku Dev Center

なお、実施前に取得したバックアップからの復元方法などを公式で軽く見ておくと良いでしょう。

不安な方や既に運用しているサービスに関しては復旧テストもしておいても良いでしょう。

Heroku PGBackups | Heroku Dev Center

アプリ名等の確認

Durability タブのページで、それぞれDB名(DATABASE_URL)アプリ名Backupバージョン名が確認できるので控えておきましょう。

f:id:inodev:20180410000234p:plain

DBを削除する

DBの権限の問題からHerokuではRailsからのDROP操作が出来ません

つまり heroku run rails db:migrate:reset 等は行なえません。

そこで、pgのアドオン用の命令で直接DBを削除してしまいます。

$ heroku pg:reset [DB名] --app [アプリ名]

例:

$ heroku pg:reset postgresql-xxxxxxxxxxx-99999  --app sushi

マイグレーションの状態確認でDBとスキーマが空であることを確認しましょう。

$ heroku run rails db:migrate:status --app sushi
Running rails db:migrate:status on ⬢ sushi... up, run.4506 (Hobby)
Schema migrations table does not exist yet.

空っぽになっていたら次回 rails db:migrate すれば、

マイグレーションファイルを全部実行してスキーマファイルを作成しなおせます。

修正したマイグレーションファイルをデプロイする

ローカルからHerokuへデプロイするという運用の方はpushしてデプロイしましょう。

$ git push production master

Herokuアプリ(web dyno)の再起動

ここで再起動しないと前のアプリの情報も含んでしまい、

前の誤った情報を含むマイグレーションファイルの構成で反映される可能性があります。

※これを行っていなかったがために1回ちゃんと反映されていなかったので気をつけるべし

$ heroku restart -r production

マイグレーションファイルの反映

$ heroku run rails db:migrate --app [アプリ名]

動作確認

$ heroku run rails db:migrate:status --app [アプリ名]

全て反映されてUPになっていればOK

再度Herokuアプリ(web dyno)の再起動

DB構成が変わっているので、念の為アプリを再起動しておいたほうが良いと思われる。

$ heroku restart --app sushi

バックアップからリストアする

メンテナンスモードにしてから取得したバックアップデータをリストアしましょう。

$ heroku pg:backups:restore [Backupバージョン名] [DB名] --app [アプリ名]

例:

$ heroku pg:backups:restore b008 postgresql-dimensional-92915 --app warm-plateau-1361

Heroku PGBackups | Heroku Dev Center

Herokuのメンテナンスモード機能をOFFにする

これを忘れてたらずっとメンテナンスモードなので使えるように戻しましょう。

動作確認

対象のアプリのDBでリストアされて以前と同様に使えることを確認しましょう。

正しくリストアしたデータにアクセス出来ていればOKです!

以上!

まとめ

普通に開発していればあまりないと思いますが、誤ったmigrationファイルをコミットしちゃった!とか、

あろうことかHerokuにデプロイまでしちゃった!という時の復旧方法でした。

自分がミスって無くても複数人で開発してたら、レビューですり抜けちゃうというのは全然ありえますしね!

もし困ったときには思い出して役立てて頂ければ幸いです!