PostgeSQL 9.4からレプリケーションスロットという機能が追加されました。
レプリケーションスロットは、レプリケーション状態や付帯情報を保持する枠組みです。これにより、レプリケーションが継続不能になったり、スタンバイサーバーへの問い合わせでコンフリクト(後述)が生じるのを防止します。
PostgreSQLのストリーミングレプリケーションでは、プライマリ、スタンバイとも、任意のタイミングでPostgreSQLサーバープロセスを停止することができ、次に起動した時にレプリケーションを継続します。ところが、レプリケーションを長く中断していると、継続不能になる場合がありました。
レプリケーションにプライマリ側のWALファイルの情報を使うのですが、一方でWALファイルは順次削除されてしまうため、長期間さかのぼることができませんでした。
この問題に対する従来の対策は、WALファイル保持数の設定を多めに指定しておく、ストリーミングレプリケーションに加えてWALファイルのアーカイブログを使ったファイル単位転送のレプリケーションを組み合わせる、というものでした。
これに対して、レプリケーションスロットがあれば「このスタンバイはどのWALファイルを必要としているか」という情報が保持されるため、ストリーミングレプリケーションのみの構成であっても、整合性保持に必要なログファイルを消してしまうことを防げます。
PostgreSQLのストリーミングレプリケーションのもう一つの課題は、コンフリクトです。ここでいうコンフリクトとは、スタンバイに対して参照SQLを実行する時に、プライマリ側の状態の都合で、エラー終了させられてしまう動作です。
最もよくあるケースが、VACUUM処理との競合です。不要データ領域を整理するVACUUM処理では、本来は参照されているデータについては「まだ有用なデータ」と判断して、整理しません。しかし、プライマリサーバー上のVACUUMは、そのデータがスタンバイサーバー側で参照されていることまでは把握できません。そのため、スタンバイサーバーでのデータ参照と、プライマリから回ってきたVACUUM処理とが競合して、コンフリクトによるエラーが発生してしまうのです。
レプリケーション遅延をさせることなく、このコンフリクトを防ぐために、従来は「VACUUMを何トランザクション分だけ保留する」という処理方法を採っていました。しかし、どのくらいの値を設定すれば大丈夫なのか、判断が難しいという欠点がありました。レプリケーションスロットによって「このデータはまだスタンバイに参照されている」という情報が、プライマリ側に保持されるようになり、無駄のないVACUUM保留が実現できます。
レプリケーションスロットは以下のように使用します。
まず、前提として、ストリーミングレプリケーションが構成されているものとします。この時、スタンバイ側にpostgresql.conf以下の設定が必要となります。
hot_standby = on hot_standby_feedback = on
プライマリ側には以下のpostgresql.confへの設定が必要です。max_wal_sendersとmax_replication_slotsは、本例では2としてありますが、より多くのスタンバイを接続する場合は、それに合わせて数を増やします。
wal_level = hot_standby max_wal_senders = 2 max_replication_slots = 2
スロットはプライマリで以下の関数を実行して作成します。
db1=# SELECT * FROM pg_create_physical_replication_slot('a_slot');
これに対して、あるスタンバイが本スロットを使うにはrecovery.confで以下を設定します。これはスタンバイPostgreSQLの再起動で反映されます。
primary_slot_name = 'a_slot'
スロットが使われているかどうかは以下のSQLで確認できます。
db1=# SELECT slot_name, active FROM pg_replication_slots; slot_name | active -----------+-------- a_slot | t (1 row)
スロットを削除するにはpg_drop_replication_slot('スロット名')関数を使います。
Copyright © ITmedia, Inc. All Rights Reserved.