PostgreSQL 9.3のストリーミングレプリケーションを使用して、マスターテーブルとスレーブテーブルにデータを挿入する間の時間を測定したいと思います。このために、2つのフィールドid(serial)、t(text)を持つテーブルtest_timeを作成します。その後、トリガーを追加しました:
cur_time:=to_char(current_timestamp, 'HH12:MI:SS:MS:US'); update test_time set t=cur_time where id=new.id;
しかし、時間は両方のテーブルで同じです。遅延時間を測定するにはどうすればよいですか
マスター側からの遅延をバイト単位で取得できます。pg_xlog_location_diff
を使用すると、バックエンドのpg_current_xlog_insert_location
エントリのマスターのreplay_location
とpg_stat_replication
を簡単に比較できます。
これは、マスターで実行する場合にのみ機能します。レプリカにはマスターがどれだけ先にあるか分からないため、レプリカからはできません。
さらに、これはsecondsの遅れを知らせません。現在の(少なくとも9.4の)PostgreSQLバージョンでは、コミットまたはWALレコードに関連付けられたタイムスタンプはありません。したがって、特定のLSN(xlog位置)がどれくらい前にあったかを知る方法はありません。
現在のPostgreSQLバージョンでレプリカラグを数秒で取得する唯一の方法は、外部プロセスにupdate
を専用のタイムスタンプテーブルに定期的にコミットさせることです。そのため、レプリカ上のcurrent_timestamp
を、レプリカ上に表示されるそのテーブル内の最新のエントリのタイムスタンプと比較して、レプリカがどの程度遅れているかを確認できます。これにより追加のWALトラフィックが作成され、PITR(PgBarmanなど)のアーカイブWALに保持する必要があります。そのため、データ使用量の増加と必要なラグ検出の粒度をバランスさせる必要があります。
PostgreSQL 9.5では、コミットタイムスタンプを追加することができます。コミットタイムスタンプを使用すると、特定のコミットが発生してからどれくらい前か、つまりレプリカが時計の秒でどれだけ遅れているかを知ることができます。
Alf162は、クレイグリンガーの答えに対するコメントで良い解決策に言及しました。明確にするためにこれを追加しています。
PostgreSQLには、管理関数 pg_last_xact_replay_timestamp() があります。これは、リカバリ中に再生された最後のトランザクションのタイムスタンプを返します。これは、そのトランザクションのコミットまたはアボートWALレコードがプライマリで生成された時間です。
したがって、レプリカに対するこのクエリselect now()-pg_last_xact_replay_timestamp() as replication_lag
は、現在のクロックとレプリケーションストリームから適用された最後のWALレコードのタイムスタンプとの時間差を表す期間を返します。
マスターが新しいミューテーションを受信していない場合、ストリーミングするWALレコードはなく、この方法で計算された遅延は、実際には複製の遅延のシグナルにならずに大きくなることに注意してください。マスターが多かれ少なかれ連続的な突然変異の下にある場合、それは連続的にストリーミングするWALになり、上記のクエリは、マスターでの変更がスレーブで具体化するための時間遅延の精密な近似です。 2つのホストのシステムクロックがどれだけ厳密に同期されているかによって、明らかに精度が影響を受けます。
データベースに頻繁に書き込みがある場合、以下のクエリはスレーブラグを取得するための近似です
select now() - pg_last_xact_replay_timestamp() AS replication_delay;
以下は、書き込みが非常に少ないデータベースのレプリケーションラグを計算するためのより正確なクエリです。マスターがスレーブへの書き込みを送信しない場合、pg_last_xact_replay_timestamp()は定数になる可能性があるため、上記のクエリを使用してスレーブの遅延を正確に判断できない場合があります。
SELECT CASE WHEN pg_last_xlog_receive_location() =
pg_last_xlog_replay_location() THEN 0 ELSE EXTRACT (Epoch FROM now() -
pg_last_xact_replay_timestamp()) END AS log_delay;
正解のわずかに異なるバージョン:
postgres=# SELECT
pg_last_xlog_receive_location() receive,
pg_last_xlog_replay_location() replay,
(
extract(Epoch FROM now()) -
extract(Epoch FROM pg_last_xact_replay_timestamp())
)::int lag;
receive | replay | lag
------------+------------+-------
1/AB861728 | 1/AB861728 | 2027
遅延は、「受信」が「リプレイ」と等しくない場合にのみ重要です。レプリカでクエリを実行する
10リリース時点:
https://www.postgresql.org/docs/10/static/monitoring-stats.html#pg-stat-replication-view
write_laginterval最近のWALをローカルでフラッシュしてから、このスタンバイサーバーが書き込んだという通知を受信するまでの経過時間(ただし、まだフラッシュまたは適用されていません)。これは、このサーバーが同期スタンバイとして構成されている場合、committing_commitレベルremote_writeがコミット中に発生した遅延を測定するために使用できます。
flush_laginterval最近のWALをローカルにフラッシュしてから、このスタンバイサーバーが書き込みおよびフラッシュしたという通知を受信するまでの経過時間それ(ただし、まだ適用されていません)。これは、このサーバーが同期スタンバイとして構成されている場合、committing_commitレベルremote_flushがコミット中に発生した遅延を測定するために使用できます。
replay_laginterval最近のWALをローカルにフラッシュしてから、このスタンバイサーバーが書き込み、フラッシュしたという通知を受信するまでの経過時間そしてそれを適用しました。これは、このサーバーが同期スタンバイとして構成されている場合、committing_commitレベルremote_applyがコミット中に発生した遅延を測定するために使用できます。
(鉱山のフォーマット)
残念ながら、新しい列は同期レプリケーションのみに適しているようです(そうでない場合、マスターは正確なラグを認識しません)。したがって、非同期レプリケーションの遅延はそのままですnow()-pg_last_xact_replay_timestamp()
...
マスターでは、select * from pg_stat_replication;
これにより、以下が得られます。
| sent_lsn | write_lsn | flush_lsn | replay_lsn
-+-------------+-------------+-------------+-------------
| 8D/2DA48000 | 8D/2DA48000 | 8D/2DA48000 | 89/56A0D500
それらはあなたのオフセットがどこにあるか教えてくれます。この例からわかるように、レプリカでの再生は遅れています。