【Unit4 ブログリレー7日目】
こんにちは、エムスリーエンジニアリンググループの堺澤です。
エムスリーではクラウド移行(=脱オンプレ)の活動が盛んに行われています。
今回は私が担当していたサービスで DB をクラウド移行したときに起きた問題について紹介したいと思います。
起きたこと
題名の通り、DB をクラウド移行したらレコードが見えなくなってしまいました。具体的には、INHERITS*1 を利用して作成された子テーブルで親テーブルにあるデータが見えなくなりました。問題発生時は検証環境では見えていて、本番環境だけこの現象が発生していました。
原因
そのサービスでは月毎に INHERITS を利用して子テーブルを作成し、親テーブルから子テーブルへはトリガーを利用して同期を取っていました。 しかし、本番環境のみトリガーが移行できておらず、親テーブルと子テーブルが独立し、親テーブルに値が入っても子テーブルに反映されない状態になっていました。サイト上の表示には親テーブルが参照されていたため即座にユーザ影響が現れたわけではありませんでしたが、子テーブルを参照するバッチでレコードが正しく読み込めなくなったことで問題が発覚しました。
子テーブルを利用する運用背景
このサービスは月単位でデータを扱うサービスで、数ヶ月後に過去のデータをバッサリ消せるようにパーティションテーブルを利用していました。子テーブル単位だと削除影響で残りテーブルを vacuum しないで良くなるのでこのような構成になっていました。
トリガーが移行されなかった理由
以下の理由でトリガー移行がされませんでした。
- 最初にテーブル全体をダンプ・リストアをしようとしたが、容量の問題でできなかった(タイムアウトした)
- なのでテーブルを指定して分割で移行するようにした
- このテーブル移行時に、トリガーの存在を認識できていなかった
検証環境ではデータが少なくテーブル全体をダンプ・リストアできてトリガーも合わせて移行できていました。そのため、事前検証では今回の問題を検知できませんでした。
対応と今後
今回は子テーブルを参照していたバッチが親テーブルを直接参照するように修正することで対応しました。今後はトリガーで同期する運用を廃止し、親テーブルにデータを集約するように修正予定です。テーブルが巨大になるとパフォーマンスに影響が出る可能性がありますが、BigQuery と連携しデータのバックアップを取ってから過去データを削除する対応を合わせてしていきます。
まとめ
DB 移行の前後でテーブルやインデックスだけでなく、トリガーの移行状態を確認するようにすることを学びました。また、当たり前ですが事前検証と違う手順で本番移行をするべきではなかったです。手順を変える場合はもう一度問題ないことを検証するように合わせて注意していきます。
他の手順として pg_dump にはスキーマ情報だけ dump するオプションもあったので、データとスキーマ(trigger なども含む)を分けて dump する方法も次回以降の検討に入れたいと思います。
We're hiring!
エムスリーではテクノロジーを活用して医療業界を変えるプロダクト作りに取り組んでいます。 エンジニア、プロダクトマネージャー、プロダクトデザイナーを絶賛募集中です。 ご興味を持たれた方はぜひご応募ください。
*1:PostgreSQL が提供するテーブルの継承機能: https://www.postgresql.jp/docs/9.4/ddl-inherit.html