方法1: バッファ・ピンを取得したまま長時間走るクエリの利用
- ① レプリケーション構成をセットアップする。
- ② マスタで、テーブルを作成する。
CREATE TABLE test1 AS SELECT id FROM generate_series(1, 10) id;
- ③ マスタで、テーブルから1レコード削除する。
DELETE FROM test1 WHERE id = 1;
- ④ スタンバイで、バッファ・ピンを取得したまま長時間走るクエリを実行する。このクエリは、テーブルを外部表、
pg_sleep()
を内部表とするネストループ結合により実現する。
SELECT * FROM test1 LEFT JOIN pg_sleep(600) ON id = 2;
- ⑤ マスタで、テーブルに対してVACUUMを実行する。
VACUUM test1;
- ⑥ max_standby_streaming_delayで指定された競合待ちの時間が経過すると、スタンバイで、④のクエリがキャンセルされて、以下のエラーメッセージが出力される。
ERROR: canceling statement due to conflict with recovery
DETAIL: User was holding shared buffer pin for too long.
方法2: カーソルの利用
- ① レプリケーション構成をセットアップする。
- ② マスタで、テーブルを作成する。
CREATE TABLE test2 AS SELECT id FROM generate_series(1, 10) id;
- ③ マスタで、テーブルから1レコード削除する。
DELETE FROM test2 WHERE id = 1;
- ④ スタンバイで、テーブルをスキャンするカーソルを作成して、1件レコードを取得する。
BEGIN;
DECLARE testcursor CURSOR FOR SELECT * FROM test2;
FETCH NEXT testcursor;
- ⑤ マスタで、テーブルに対してVACUUMを実行する。
VACUUM test2;
- ⑥ max_standby_streaming_delayで指定された競合待ちの時間が経過すると、スタンバイで、④のトランザクションを実行していたセッションが強制終了されて、以下のエラーメッセージが出力される。
FATAL: terminating connection due to conflict with recovery
DETAIL: User was holding shared buffer pin for too long.
HINT: In a moment you should be able to reconnect to the database and repeat your command.