10

ロードバランサで複数のWEBサーバに処理を分散していて、WEBサーバは一つのDBサーバを参照しているrailsアプリがあります。

運用している中で、テーブルのカラムを削除する必要がある場合、マイグレーションファイルでremove_columnをすると思うのですが、 capistranoで全てのWEBサーバにデプロイする中で、デプロイ対象のWEBサーバが多いとWEBサーバでは削除したカラムを参照しますが、 DB側はrake db:migrateが実行されたためにカラムが削除されているという状況が発生するような気がしています。

このような事象が発生しないように複数サーバへのデプロイを行うにはどうすればよいでしょうか?

Yujiro Arai
  • 193
  • 1
  • 9

2 Answers2

9

すぐには消さない、という戦略が考えられます。

リリースを2回に分け、
1回めのリリースで、すべてのアプリケーションサーバを、そのカラムにアクセスしない版に更新します。
次のリリースで、要らなくなったカラムをDBから実際に消す、という寸法です。

カラム名の変更についても、基本的には同じ考え方が適用できるかと思います。

# いっぺんにやってひどい目にあったことが何度か (´・ω・`)

KoRoN
  • 5,182
  • 1
  • 16
  • 35
  • 1
    ありがとうございます!自動でデプロイしている場合は、【カラム削除の場合】 → 1. アプリケーションサーバを削除するカラムを参照しないバージョンに更新 2. DBのマイグレーション。 【カラム追加の場合】 1. DBのマイグレーション 2. アプリケーションサーバを新しいカラムを参照するバージョンに更新。【カラムの変更】 → ゆるさない!一回のコミットでは、カラムの追加と削除を両方含めない。という感じで運用している感じですかね。 – Yujiro Arai Dec 08 '14 at 09:06
  • 削除と追加の場合はそのとおりです。
    変更の場合はちょっと複雑になりますが
    1. カラムを追加するDBマイグレーション
    2. 「旧カラムから読む + 新旧両カラムに書く」サーバをデプロイ
    3. 旧カラムから新カラムへ データ をマイグレーションするバッチを実行
    4. 「新カラムだけを読み書きする」サーバをデプロイ
    5. 旧カラムを削除するDBマイグレーション

    ってな感じになります。

    – KoRoN Dec 08 '14 at 09:54
  • カラムの変更にもちゃんと対応してデプロイを自動化しているんですね!!ご回答頂きありがとうございます!! – Yujiro Arai Dec 08 '14 at 10:02
5

単純なカラム削除や追加であれば、KoRoNさんの回答の通り、アプリ側とDB側のリリースを分けたり、自動マイグレーションであれば2回に分けて段階的にリリースするのがセオリーですね。

追加情報として、カラム名の変更や、より複雑なスキーマ変更に関しては、ちょうどそういったDBの変更技法を扱った「データベース・リファクタリング」という書籍があり、一冊丸ごと様々な手法が紹介されています。

http://amzn.to/131cVYy (AA)

以前にこの本の読書会が何回か開かれたようで、日本語の情報もあります。

ento
  • 2,202
  • 5
  • 20
  • 35
nekoruri
  • 89
  • 2
  • リンクをクリックしなくても、ある程度リンク先の内容がわかるように概要を入れました。気に入らないところがあれば (お手数ですが) 上書き[edit]してしまってください。 – ento Dec 09 '14 at 15:03
  • ありがとうございます!データベース・リファクタリングという書籍についてははじめて知りました!DBのことをもっと深く知ることで、もっと効率的にデプロイする方法が見つかりそうですね!学びます! – Yujiro Arai Dec 10 '14 at 00:45