Hatena::Grouppostgresql

PostgreSQL 雑記 このページをアンテナに追加 RSSフィード

2010-06-13PG9.0 スタンバイの遅延確認 このエントリーを含むブックマーク このエントリーのブックマークコメント

PostgreSQL 9.0 の非同期レプリケーションで、スタンバイがどれだけマスタから遅れているかを確認する方法の紹介です。一応オーバーヘッドや遅延の少ないレプリケーション方式とはいえ、遅れが広がっていかないかは確認しておいたほうが良いでしょう。特に更新頻度が高い場合、マルチプロセスで処理できる (=複数のCPUで並列処理できる) マスタ側と比べて、1個のリカバリプロセスだけで操作をリプレイするスタンバイ側では、追いつけない負荷パターンも確認されています。

さて、9.0 で可能な遅延の確認方法ですが、直接的に "遅れ時間" を取得する方法はありません。代わりに利用できるのは、トランザクションログ (WAL) のどの位置を処理しているかという情報です。すべての更新処理は、WAL という一連のストリームとしてシリアライズされるため、この位置を確認することで "遅れバイト数" を計算できます。具体的には、以下の関数を使います。

  • マスタ側
    • WAL書き出し位置 : pg_current_xlog_location()
  • スタンバイ側
    • WAL受信位置 : pg_last_xlog_receive_location()
    • WALリプレイ位置 : pg_last_xlog_replay_location()

マスタとスタンバイの両方にログインし、それぞれの値を取得する必要がありますが、(current - receive) で送信遅延を、(current - replay) でリプレイ遅れ (参照した際の遅れ) の量を計算できます。また、間接的ではありますが、定期的にこれらの値を取得しておけば、単位時間当たりの WAL 位置が進む "速度" も計算できるので、遅れ時間を見積もることも可能でしょう。

……と簡単に言いましたが、実はまだ罠があり、それは "引き算" の部分です。これらの関数は全て ”32bit16進数/32bit16進数” という text 型を返すので、そのままでは引き算できません。64bit のフラットなアドレスに変換したいところですが、ここで (たぶん) ドキュメント化されていない計算式が必要になります。特にうっかりしやすいのは、232 * 255/256 で繰り上がるという、非線形なアドレスを使っていることです。しかも、デフォルトでは16進数文字列から数値に変換する関数が提供されていないようなので、先日の from_hex() を使っています。これらの手順を関数に落とすと↓のようになります。

=# CREATE FUNCTION pg_xlog_pos(text) RETURNS bigint AS
   $$
   SELECT from_hex(xpos[1]) * 16 * 1024 * 1024 * 255 + from_hex(xpos[2])
     FROM regexp_matches($1, '([0-9A-F])+/([0-9A-F]+)') AS xpos
   $$
   LANGUAGE sql IMMUTABLE STRICT;

=# SELECT pg_xlog_pos(pg_current_xlog_location());
 pg_xlog_pos
-------------
    29872128

こういった処理はオフィシャルで用意してくれると良いのですが、9.1 には入るでしょうか? また、もし外部からこれらの値を取得するならば、死活監視も兼ねられるので、フェイルオーバーの自動化も含めて、レプリケーション総合監視ツールとしてまとまっていると嬉しいかもしれません。