本番稼働中のDBにNOT NULL制約かつデフォルト値のないカラムを追加する

はじめに

株式会社ユーザベース スピーダ事業 竹澤です。

この記事の内容としては、本番稼働中のAPIを止めずに、APIが参照しているDBにNOT NULL制約のあるカラムを追加する1つの方法の紹介です。

私はさまざまなSPEEDAのマイクロサービスから財務値を取得できるような、コアな財務APIの開発に携わっていました。 当初の設計では変則決算を考慮していなかったのですが、開発を進めていくうちに変則決算も必要になりました。

アプリケーションの構成

まずは、ここでこの財務APIの構成を紹介します。 本記事で不要な部分に関しては、省略しています。

ユーザーがAPIを叩くと、アプリケーションは財務API用DBに財務値を取得しにいき、その値を返します。

参照フロー

財務API用DBに財務値を登録する際は、

  1. 社内のデータ組成チームが組成したCSVファイルを、 Cloud Storage に置いてもらう
  2. Cloud Functions が Cloud Storage の変更を検知し、財務APIの登録用のエンドポイントを叩く
  3. 財務APIは Cloud Storage 上のCSVから財務データを取得し、DBに登録する

という流れになっています。

登録フロー

問題

変則決算に対応するために、既存のDBのテーブルにカラムを追加する必要が出てきたのですが、このAPIは本番稼働中のためサービスを止めることが難しかったです。

アプリケーションを開発し始めた当初は変則決算を考えていなかったので、DBにはperiod(四半期、半期、通期のいずれか)と決算期間末の年月のみを持っていました。

上記のデータさえあれば、会計期間を算出することができるからです。

例えば、通期(FY4)で決算期間末が2025/12の場合は、同じ決算の上半期(HF1)の会計期末は、決算期末の6ヶ月前になるので、2025/06と求めることができます。

しかし、変則決算のデータも持つようになると、会計期末を計算して求めることができなくなります。

そのため、テーブルに会計期末を持つカラムを追加する必要が出てきました。

追加するカラムにデフォルト値を入れることができれば楽だったのですが、変則決算の場合はデフォルト値がわからないため、デフォルト値を入れることは不可能でした。

解決方法

SREに相談したところ、下記のような方法を提案されました。

  1. 現在稼働しているDB(以下元々のDB)をコピーした新しいDB(以下避難用DB)を作成する

  2. 社内のデータ組成チームに、一時的に登録を止めてもらう

  3. 元々のDBに貼られていたDNSの向き先を、避難用DBへ変更する(この時点で、APIは避難用DBを見るようになります)

  4. 元々のDBにカラムを追加する

  5. 元々のDBに追加したカラムに、値を入れる

  6. 避難用DBに向いていたDNSの向き先を、元々のDBに戻す

  7. データ組成チームの登録を再開する

  8. しばらく運用してみて問題がなさそうだったら、避難用DBを削除する

これで、無事元々のDBにカラムが追加され、ユーザーはカラムの追加されたDBをAPI経由で見れるようになりました。

最後に

この方法は、DBへの読み込みはいつ行われるか分からないが、書き込みは自分たちでタイミングを調整できるのでうまくいく方法でした。

DBの読み込みタイミングも書き込みタイミングも自分たちで調整できない場合は、別の方法を考える必要があります。

Page top