Pgpool-II 4.6 の紹介

2025 年 2 月 28 日、Pgpool-II の新しいメジャーバージョン 4.6 がリリースされました。

Pgpool-II 4.6 では、ロギングコレクター、クエリキャッシュの機能強化がされました。また、バックエンドからのメッセージのログ機能の搭載、PostgreSQL 17 への対応、Watchdog の IPv6 への対応も行われました。

Pgpool-II 4.6 の新機能及び変更点は Pgpool-II 公式ドキュメントの以下のページに記載されています。

Pgpool-II 4.6 リリースノート

本記事では、これらの新機能について詳しく紹介します。

ログのローテーションを指示する新しい PCP コマンド

Pgpool-II には、PostgreSQL のロギングコレクター(logging_collector) と同様のログ収集機能が備わっています。

ロギングコレクターを使ってログを収集する場合、これまではロギングコレクターにシグナルを送ることでしかログのローテーションを行えませんでしたが、pcp_log_rotate コマンドを使用することで Pgpool-II のログファイルを簡単にローテーションできるようになりました。

動作確認のための設定例は以下の通りです。

(pgpool.conf 設定例)
log_destination = 'stderr' 
logging_collector = on 
log_directory = '/var/log/pgpool_log' 
log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log'

log_directory で指定したディレクトリを確認すると、現時点でのログが出力されていることが確認できます。

[root@server1 ~]# ls -l /var/log/pgpool_log/
合計 4
-rw-------. 1 postgres postgres 193 6月 9 16:21 pgpool-2025-06-09_162145.log

その後、 pcp_log_rotate を実行することで新しいログファイルへとローテートされていることが確認できます。

[root@server1 ~]# pcp_log_rotate -h 192.168.100.50  -p 9898 -U pgpool -W
Password:
pcp_log_rotate -- Command Successful

[root@server1 ~]# ls -l /var/log/pgpool_log/
合計 8
-rw-------. 1 postgres postgres 284 6月 9 16:21 pgpool-2025-06-09_162145.log
-rw-------. 1 postgres postgres 193 6月 9 16:21 pgpool-2025-06-09_162159.log

また -s scope オプションによってコマンドの与える影響範囲を指定することができます。サポートされているコマンドスコープは以下です。(デフォルトは local)

  • c, cluster : クラスタを構成するすべての Pgpool-II のログファイルをローテーションします。
  • l, local : ローカル Pgpool-II のログファイルをローテーションします。

リロードによる logging_collector 関連のパラメータの変更

logging_collector 関連の以下の設定パラメータの変更が、Pgpool-II のリロードで反映されるようになりました。これにより logging_collector の設定の反映のために Pgpool-II の再起動の必要がなくなりました。

  • log_truncate_on_rotation
  • log_directory
  • log_filename
  • log_rotation_age
  • log_rotation_size
  • log_file_mode

リロードで設定が反映されるかの動作確認として log_filename の値を変更したうえで pcp_log_rotate コマンドを実行してログファイルの名前が変更されて出力されるかを確認します。

まず、pgpool.conf を以下の設定に変更し、 Pgpool-II をリロードします。

[root@server1 ~]# vi /etc/pgpool-II/pgpool.conf
#log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log'
log_filename = 'pgpool-%a.log'

[root@server1 ~]# systemctl reload pgpool.service

その後 pcp_rotate_log コマンドを実行すると出力されるログファイルの名前が変更されていることが確認できます。

[root@server1 ~]# ls -l /var/log/pgpool_log/
合計 8
-rw-------. 1 postgres postgres 284  6月 12 09:51 pgpool-2025-06-12_095140.log
-rw-------. 1 postgres postgres 193  6月 12 09:51 pgpool-2025-06-12_095142.log

[root@server1 ~]# pcp_log_rotate -U pgpool -W -h 192.168.100.50
Password:
pcp_log_rotate -- Command Successful
[root@server1 ~]# ls -l /var/log/pgpool_log/
合計 12
-rw-------. 1 postgres postgres 284  6月 12 09:51 pgpool-2025-06-12_095140.log
-rw-------. 1 postgres postgres 411  6月 12 09:52 pgpool-2025-06-12_095142.log
-rw-------. 1 postgres postgres 361  6月 12 09:52 pgpool-Thu.log

クエリキャッシュの強制的な作成

クエリキャッシュSELECT クエリの実行結果を共有メモリに保存し、同じクエリ(パラメータ、データベース、ユーザ含む)が実行されたら、結果を再利用する機能です。PostgreSQL にアクセスせず、ディスクアクセスもないので極めて高速に問い合わせ結果を返すことができます。

Pgpool-II では、クエリキャッシュは通常自動的に作成されますが、安全性の観点から、immutable でない関数を含むクエリ (たとえば SELECT now();) はキャッシュされない仕様になっています。

以下の実行例では、クエリを実行するたびに結果が変化していることがわかります。

postgres=> SELECT now();
now
-------------------------------
2025-06-12 17:10:27.241885+09
(1 行)

postgres=> SELECT now();
now
-------------------------------
2025-06-12 17:10:29.156295+09
(1 行)

また、ログからも毎回 PostgreSQL にアクセスしていることが確認できます。

2025-06-12 17:10:27.241: psql pid 2628: LOG: DB node id: 1 backend pid: 2644 statement: SELECT now();
2025-06-12 17:10:29.155: psql pid 2628: LOG: DB node id: 1 backend pid: 2644 statement: SELECT now();

それでも、内容を理解したうえでキャッシュを行いたいユースケースが存在することから、今回のリリースではクエリキャッシュを強制的に作成する機能が追加されました。クエリの先頭に /*FORCE QUERY CACHE*/ を付けて実行することで、クエリキャッシュを強制的に作成できるようになります。

以下のようにクエリを実行することで、キャッシュされた時点のタイムスタンプが返されていることが確認できます。このキャッシュは Pgpool-II を再起動するまで保持されます。

postgres=> /*FORCE QUERY CACHE*/SELECT now();
now
------------------------------
2025-06-12 17:14:47.297804+09
(1 行)

postgres=> /*FORCE QUERY CACHE*/SELECT now();
now
------------------------------
2025-06-12 17:14:47.297804+09
(1 行)

さらに、ログにもキャッシュが利用されていることが記録されています。

2025-06-12 17:14:47.297: psql pid 2621: LOG: DB node id: 0 backend pid: 2901 statement: /*FORCE QUERY CACHE*/SELECT now(); 
2025-06-12 17:14:50.138: psql pid 2621: LOG: fetch from memory cache 
2025-06-12 17:14:50.138: psql pid 2621: DETAIL: query result fetched from cache. statement: /*FORCE QUERY CACHE*/SELECT now();

また /*NO QUERY CACHE*/ を冒頭に付記して宣言しても、 宣言したクエリキャッシュを削除することは出来ません。 /*NO QUERY CACHE*/ はキャッシュエントリが作成されないようにするだけなためです。

Pgpool-II を再起動することなく作成したクエリを削除する場合は、後述する PGPOOL SET CACHE DELETE コマンドか、pcp_invalidate_query_cache コマンドを使用する必要があります。

新しい PGPOOL SET CACHE DELETE コマンド

登録されているクエリキャッシュを削除する PGPOOL SET CACHE DELETE コマンドが追加されました。引数としてクエリの文字列を渡すことによってクエリキャッシュを指定して削除することができます。

postgres=> /*FORCE QUERY CACHE*/SELECT now();
              now
-------------------------------
 2025-06-12 09:58:49.983346+09
(1 行)

postgres=> PGPOOL SET CACHE DELETE '/*FORCE QUERY CACHE*/SELECT now();';
NOTICE:  query cache deleted. query: "/*FORCE QUERY CACHE*/SELECT now();"
SET
postgres=> /*FORCE QUERY CACHE*/SELECT now();
              now
-------------------------------
 2025-06-12 09:59:32.998492+09
(1 行)

引数に記述するクエリキャッシュはクエリ文字列は、末尾の「;」も含めて以前のクエリと完全に一致していなければならず、一致しない場合は以下エラーとなります。

postgres=> PGPOOL SET CACHE DELETE '/*FORCE QUERY CACHE*/SELECT now()'; -- 末尾の ';' が不足
NOTICE: query cache does not exist for query: "/*FORCE QUERY CACHE*/SELECT now()" -- クエリキャッシュが存在しないエラーとなる
SET

クエリキャッシュを削除する新しい PCP コマンド

すべてのクエリキャッシュを削除する PCP コマンド、pcp_invalidate_query_cache が追加されました。

今までは、クエリキャッシュの削除は Pgpool-II の再起動が必要でしたが、このコマンドを実行することによって Pgpool-II を再起動することなくクエリキャッシュを削除することができます。

/*FORCE QUERY CACHE*/」で 「SELECT now();」 クエリをキャッシュします。

postgres=> /*FORCE QUERY CACHE*/SELECT now();
now
-------------------------------
2025-06-09 13:50:37.066191+09
(1 行)

その後、 pcp_invalidate_query_cache を実行すると、クエリキャッシュを削除することができます。

[postgres@server1 ~]$ pcp_invalidate_query_cache -h 192.168.100.50 -p 9898 -U pgpool -W
Password:
pcp_invalidate_query_cache -- Command Successful

postgres=> /*FORCE QUERY CACHE*/SELECT now(); -- クエリキャッシュが削除されているため再作成となる
now
-------------------------------
2025-06-09 13:50:56.561619+09
(1 行)

新しい設定パラメータ log_backend_messages

バックエンドからのメッセージログを出力する log_backend_messages パラメータが追加されました。terse または verbose に設定されている場合、バックエンドからのメッセージをログ出力します。

以下が受け取るメッセージ例です。

2025-06-09 14:00:57.494: psql pid 7579: LOG: last ParameterStatus message from backend 0 repeated 13 times

terse では、同じ種類のメッセージが同じバックエンドから送られてくると、その回数を記録し、次に異なる種類のメッセージが送られてきた時に繰り返し回数を報告します。そのため、繰り返している最中にセッションに対応するプロセスが強制終了すると、その分のログが出力されません。この場合でもすべてのログを出力するには、 verbose オプションを使用します。

verbose に設定したときのログ出力例は以下です。同一内容のメッセージであっても送られてくるたびに出力するためプロセスの強制終了によるログの損失は避けられますが、大量のメッセージがバックエンドから送られてくる場合は注意が必要です。

2025-06-09 13:58:16.390: child pid 7263: LOG: ParameterStatus message from backend 0
2025-06-09 13:58:16.390: child pid 7263: LOG: ParameterStatus message from backend 0
2025-06-09 13:58:16.390: child pid 7263: LOG: ParameterStatus message from backend 0

PostgreSQL 17 の SQL パーサの導入

Pgpool-II ではメジャーリリースするたびに、PostgreSQL の最新パーサを移植しています。今回のリリースでは PostgreSQL 17 の新しいパーサを取り込みました。

Pgpool-II の負荷分散機能では、SQL を解析して参照か更新かを判別し、どのノードに振り分けるかを決めています。そのため、PostgreSQL の新バージョンでの SQL の変更に対応するには、SQL パーサを移植する必要があります。

PostgreSQL 17 での SQL のおもな変更点は以下のとおりです。

  • MERGE への NOT MATCHED BY SOURCERETURNING 句の追加
  • COPY オプションの ON_ERROR ignoreLOG_VERBOSITY の追加
  • COPY FROM オプションの FORCE_NOT_NULLとFORCE_NULL で「*」 を使用した全列を指定できる機能の追加
  • EXPLAIN への SERIALIZEMEMORY オプションの追加
  • ALTER TABLESET STATISTICS DEFAULT を用いて、デフォルトの統計上情報ターゲットとする列の指定できる機能の追加
  • ALTER TABLE での列の生成式を変更する機能の追加
  • ALTER TABLE.. SET ACCESS METHOD のデフォルトを指定できる機能の追加
  • イベントトリガでログインイベントと REINDEX  を扱う機能の追加

Pgpool-II 4.6 では上記の変更点に対応しています。

Watchdog の hostname と heartbeat_hostname パラメータの IPv6 対応

これまで、IPv6 に対応していたパラメータは以下の通りです。

  • backend_hostnameX
  • listen_addresses
  • pcp_listen_addresses

一方で、以下の Watchdog 関連パラメータはこれまで IPv6 に対応していませんでした。

  • hostname
  • heartbeat_hostname

今回のリリースにより、hostnameheartbeat_hostname も IPv6 に対応し、すべてのネットワーク関連パラメータで IPv6 アドレスを利用できるようになりました。

おわりに

今回は、Pgpool-II 4.6 の新機能について紹介しました。

Pgpool-II 4.6 では、より実用的で便利な機能が数多く追加・改善されています。PostgreSQL の高可用性構成や負荷分散の実現を検討されている方にとって、Pgpool-II は有力な選択肢です。ぜひこの機会に Pgpool-II の導入をご検討ください。