やる気がストロングZERO

やる気のストロングスタイル

【PostgreSQL】 online alter tableを考える

Django migrationをオンラインで行えるのかどうか考えていた。

オンラインで行えるのかどうかはDjangoのmigrationコマンドの問題ではなく、使っているDB(今回の場合だとPostgreSQL)がどのようにロックを行うのかによるということがわかった。

では具体的にどうすれば良いのかを調べてみたのでメモ。(未検証なので注意。)

参考)
PostgreSQLで安全にテーブル定義を変更する - LCL Engineers' Blog

どうなるとダウンタイムが発生してしまう?

ALTER TABLEを実行した対象テーブルが排他ロック(参照も更新もできない)を取って、かつ完了までに長時間かかってしまう場合に、そのテーブルを参照・更新するリクエストが返らなくなってしまう。

PostgreSQLの場合、
カラム追加(Default制約なし)やカラム削除などは一瞬で終わるらしい。
一瞬で完了するなら排他ロックをとっても特に問題ない。(デッドロックには注意)

問題は、どうしても時間がかかってしまう変更(not null追加など)

どうすればいいか?

mysqlならオンラインでAlterできる仕組みが5.6以降あるらしい。

仕組みとしては、

  • 内部で別途、変更後構造のテーブルを構築
  • 変更前テーブルから変更後テーブルへデータをコピー。トリガーなどを使って変更前テーブルへの更新は変更後テーブルへも適用されるようになっており、データが常に同期された状態になる。
  • データ同期が完了した時点でテーブルを入れ替える

PostgreSQLにはこの仕組はない。
独自に同じことをすればよさそう?
(※pg_repackをつかえば自動で行えるかも?)

  • 変更後構造のテーブルを新規追加
  • データコピーとトリガーを使って変更前テーブルと変更後テーブルのデータ内容を同期
  • 同期が完了したタイミングでテーブルを入れ替え。