PostgreSQLに組み込まれているバックアップメカニズムは、必ずしも非常に適しているとは限りません。 PGデータをバックアップすると同時にバックアップしたい外部データがあるため、アプリケーションを quiescent 状態にしたい場合があります。ただし、アプリケーションを休止状態にする唯一の方法は、データベースも「ロック」することです。 PGには、データベース全体またはクラスター全体のロックメカニズムがありません。 PGを読み取り専用状態にすることは、次のソリューションの一部になります。
インターネット上の他の場所で回答を選別した後、私は解決策を考案しました。他の答えはそれ自体、不完全でした。ですから、他の人の利益になることを期待して、ここで答えを提示します。
default_transaction_read_only
_設定をtrue
に設定します。それが行われると、(私の解決策では):
CHECKPOINT
を実行します(これが最も安全だと思いますが、pg_xlog_switch()
は非常に高負荷のサーバーに適しています)pg_stat_clear_snapshot()
を参照読み取り/書き込み状態の復元はそれほど単純ではないです。読み取り専用接続が存在する場合、新しい読み取り/書き込みステータスを有効にするには、それらを終了する必要があります。しかし、既存の接続を削除している間に新しい接続が到着する可能性があります。もう一度、あなたは
false
に変更します別の戦略は、アプリケーションが使用するロールの権限を変更することです。これはかなり厄介で、一般的ではありません。
たとえば、テーブルだけでなく、シーケンス、ラージオブジェクト、そしておそらくスキーマ自体に対する取り消し/再付与を行う必要があります。さらに、アクセスを変更したときの既存の接続の動作は正確には何ですか?おそらく影響はありません。つまり、これらのバックエンドも強制終了する必要があります。最後に、アプリケーションにはほとんどのテーブルへの読み取り/書き込みアクセス権がありますが、スキーマ内の他のテーブルへのアクセス権はありません。再付与にそれらのオブジェクトも含まれていないことを確認する必要があります。
別の可能性は、カタログをクエリして動的クエリを実行することにより、すべてのテーブルをロックすることです。それは私の好みにとって危険なようでした。
データベースインスタンス名は「gitlabhq」、アプリケーションのユーザー名は「gitlab」です。それをあなた自身のものに置き換えてください:
_ psql -Upostgres <<'PAUSE_DB'
-- 1. disable new connections
alter database gitlabhq_production with allow_connections = off;
-- 2. Make DB read-only
alter database gitlabhq set default_transaction_read_only = true;
-- 3. Inobtrusively but safely terminate current connections
DO $X$ BEGIN
-- kill open idle connections, try up to 9x. Last time, kill regardless
FOR i IN 1..10 LOOP
PERFORM pg_terminate_backend(pid) from pg_stat_activity where usename = 'gitlab'
and (i >= 10 OR state in ('idle', 'disabled' ));
PERFORM pg_stat_clear_snapshot();
EXIT WHEN NOT EXISTS ( select pid from pg_stat_activity where usename = 'gitlab' );
RAISE NOTICE 'pg backends still open: sleeping 2 seconds';
PERFORM pg_sleep(2);
PERFORM pg_stat_clear_snapshot();
END LOOP;
-- send notice if still open connections
IF EXISTS ( select pid from pg_stat_activity where usename = 'gitlab' ) THEN
RAISE NOTICE 'Hung backends. Backup might not be 100%% consistent';
END IF;
END;$X$;
-- 4. Allow read-only connections while checkpointing/snapshotting
alter database gitlabhq with allow_connections = on;
CHECKPOINT;
_
_ alter database gitlabhq_production with allow_connections = off;
alter database gitlabhq set default_transaction_read_only = false;
SELECT pg_stat_clear_snapshot();
SELECT pg_terminate_backend(pid) from pg_stat_activity where usename = 'gitlab';
alter database gitlabhq with allow_connections = on;
_
この最後のステップで長時間実行の読み取り専用/ SELECTクエリを強制終了する可能性がありますが、私の経験では、そのような長時間実行クエリは数時間ではなくても数分続く可能性があり、稼働時間を確保するためにこれらを強制終了することは許容されます。みんな。
個人的には、この機能を公式のPostgreSQL機能として持つことが望ましいと思います。
PostgreSQL拡張機能のCコーディングに手を染めたくない場合は、PostgreSQLの前に接続プーラーを置くだけです。 pgBouncerのように。
pgBouncer 組み込みのアプリケーションアクティビティを一時停止する機能があります 。それを非常に便利にするために、(pgbouncer経由ではなく)直接接続し、新しい接続の着信を一時停止したら、アクティブな接続をキャンセルする必要があります。select pg_terminate_backend(pid) from pg_stat_activity where pid <> pg_backend_pid()
だけです。
ただし、手を汚したい場合は、C拡張機能を使用して行うことができます。拡張機能は次の条件を満たす必要があります。
_shared_preload_libraries
_にロードして、db_is_lockedのようなブールフラグで小さな静的共有メモリセグメントを登録できるようにします。
Shmemでis-lockedフラグをテストする_ProcessUtility_hook
_と_ExecutorStart_hook
_を登録し、設定されている場合は、フラグが再びクリアされるまでWaitLatch
ループでスリープします。 (代わりにパーサーフックを使用することもできます)。
Cで2つのSQL呼び出し可能関数を記述します。1つはフラグを設定します。もう1つはフラグをクリアし、PGPROC
を繰り返してすべてのユーザープロセスのラッチを設定するため、ユーザーはすぐにウェイクアップすることがわかります。
必要に応じて、フラグが設定されている場合にPGXACT
を反復して3番目の関数を記述し、開いている書き込みトランザクションを見つけて、それらに終了するように通知します。
これはすべて BDR拡張 の一部としてすでに実装されていますが、それははるかに大きなシステムの一部です。関連する部分を独自の拡張機能に抽出する可能性があります。 _bdr_locks.c
_、_bdr_commandfilter.c
_、_bdr_executor.c
_、_bdr.c
_などを参照してください。
これにより、PostgreSQLがディスク上で読み取り専用にならないことに注意してください-チェックポインタは引き続き実行され、bgwriterは引き続き実行され、アーカイバは引き続き実行されますしたがって、アトミックファイルシステムのスナップショットまたはpg_start_backup()
/pg_stop_backup()
なしでDBバックアップを作成するだけでは不十分です。しかし、DBでアプリケーションの活動を一時停止して、ユースケースとしては問題ありません。