<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>越野 太基 (Taiki Koshino) &#8211; SRA OSS Tech Blog</title>
	<atom:link href="https://www.sraoss.co.jp/tech-blog/author/koshino/feed/index.xml" rel="self" type="application/rss+xml" />
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<description>OSS専門の技術ブログ。PostgreSQL、Zabbixを中心に10種類以上のOSSの解説、アップデート情報、運用ヒントを提供。</description>
	<lastBuildDate>Wed, 04 Nov 2026 06:57:44 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2018/07/blog-icon-150x150.png</url>
	<title>越野 太基 (Taiki Koshino) &#8211; SRA OSS Tech Blog</title>
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>ロジカルレプリケーションによるメジャーバージョンアップ手順</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/version_up_with_logical_replication/</link>
		
		<dc:creator><![CDATA[越野 太基 (Taiki Koshino)]]></dc:creator>
		<pubDate>Thu, 18 Jun 2026 02:17:26 +0000</pubDate>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[アップグレード]]></category>
		<category><![CDATA[ロジカルレプリケーション]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=20608</guid>

					<description><![CDATA[PostgreSQL のメジャーバージョンアップにはいくつかの手法がありますが、本記事ではその中でもロジカルレプリケーションを利用した方法を紹介します。ロジカルレプリケーションを用いることで、新旧バージョンのデータベース ...]]></description>
										<content:encoded><![CDATA[<p data-start="42" data-end="215">PostgreSQL のメジャーバージョンアップにはいくつかの手法がありますが、本記事ではその中でもロジカルレプリケーションを利用した方法を紹介します。ロジカルレプリケーションを用いることで、新旧バージョンのデータベースを並行稼働させながらデータを同期できるため、切り替え時のダウンタイムを最小限に抑えたアップグレードが可能です。その具体的な手順とあわせて、実施時に注意すべきポイントについて解説します。</p>
<p><span id="more-20608"></span></p>
<p>なお、PostgreSQLのロジカルレプリケーション自体についての基本的な解説は、以下の記事を参考にしてください。</p>
<ul>
<li><a href="https://www.sraoss.co.jp/tech-blog/pgsql/logical-replication-1/">ロジカルレプリケーションの紹介 (1)</a></li>
<li><a href="https://www.sraoss.co.jp/tech-blog/pgsql/logical-replication-2/">ロジカルレプリケーションの紹介 (2)</a></li>
<li><a href="https://www.sraoss.co.jp/tech-blog/pgsql/logical-replication-3/">ロジカルレプリケーションの紹介 (3)</a></li>
</ul>
<h2>ロジカルレプリケーションによるアップグレードの概要</h2>
<p>ロジカルレプリケーションを利用することで、異なるメジャーバージョン間でデータを同期しながら新しい環境を構築することが可能です。新旧データベースを並行稼働させ、最終的に接続先を切り替えることで、数秒程度のダウンタイムで移行を実現できます。</p>
<p><img fetchpriority="high" decoding="async" class="alignnone wp-image-20681" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/04/c8c5fe3773c42d0664e040faf8c8014d-221x300.png" alt="" width="581" height="789" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/04/c8c5fe3773c42d0664e040faf8c8014d-221x300.png 221w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/04/c8c5fe3773c42d0664e040faf8c8014d-157x214.png 157w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/04/c8c5fe3773c42d0664e040faf8c8014d-191x260.png 191w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/04/c8c5fe3773c42d0664e040faf8c8014d.png 609w" sizes="(max-width: 581px) 100vw, 581px" /></p>
<p>上記イメージはロジカルレプリケーションを用いたバージョンアップのアーキテクチャイメージです。</p>
<p>対応バージョンとしては、Publisher（旧バージョンのデータベース）は PostgreSQL 10 以上である必要があります。例えば PostgreSQL 13 から 16 へのアップグレードは可能ですが、9.6 からの移行には対応していません。</p>
<p>全体の流れは以下のとおりです。これらの手順について詳しく解説します。<br />
ロジカルレプリケーションはデータベース単位で構成されるため、各データベースごとに個別に設定・同期を行います。</p>
<ol>
<li>旧バージョンのデータベースを稼働させたまま、新バージョンのデータベースクラスタを initdb で構築し起動する</li>
</ol>
<p>以下の手順を、対象となるすべてのデータベースに対して実施します。</p>
<ol start="2">
<li>旧バージョンの各データベースで全テーブルを対象としたパブリケーションを作成</li>
<li>新バージョン側に移行するデータベースを作成</li>
<li>旧バージョンの各データベースから pg_dump -s でスキーマ定義の SQL を取得して新バージョンの各データベースにリストア</li>
<li>新バージョンの各データベースでサブスクリプションを作成</li>
</ol>
<p>すべてのデータベースでサブスクリプション作成および同期が完了した後、<br />
以下の作業を実施します。</p>
<ol start="6">
<li>旧バージョンのデータベースクラスタへの更新処理を停止する</li>
<li>各データベースで pg_stat_subscription を確認し、LSN の一致を確認する</li>
<li>同期完了後、シーケンス位置やラージオブジェクトなどロジカルレプリケーションで同期されないデータを各データベースで手動同期する</li>
<li>アプリケーションの接続先を切り替える</li>
</ol>
<h2>ロジカルレプリケーションによるアップグレードの注意点</h2>
<p class="isSelectedEnd">ロジカルレプリケーションでは、テーブルの行データに対する変更がサブスクライバへ同期されます。一方で、行データ以外の更新情報は同期されません。</p>
<p>そのため、以下のようなオブジェクトは別途作成または移行する必要があります。</p>
<ul>
<li>テーブルやスキーマの定義</li>
<li>ビューおよびマテリアライズドビューの定義</li>
<li>パーティションテーブルや外部テーブルの定義</li>
<li>シーケンスの現在値</li>
<li>ラージオブジェクト</li>
<li>拡張機能</li>
<li>UNLOGGED TABLE</li>
<li>ロール</li>
</ul>
<p>特にスキーマ、テーブル定義についてはロジカルレプリケーションでは同期されず、サブスクライバ側で定義されていない状態でロジカルレプリケーションを行うと伝播先のテーブルがないとしてレプリケーションに失敗します。よってスキーマ、テーブル定義については pg_dump を用いて定義の SQL を取得して新バージョンのデータベースで実行するなどして事前にリストアしておく必要があります。今回紹介する手順では pg_dump に -s  オプションを付与して実行し、各 DDL を取得してロジカルレプリケーション前に新バージョンのデータベースで実行するようにします。</p>
<p>またその他にも拡張機能やロールなどもロジカルレプリケーションでレプリケーションされないため必要に応じて別途リストアする必要があります。</p>
<h2>アップグレード手順</h2>
<h3>旧バージョンデータベースのロジカルレプリケーションのセットアップ</h3>
<p>今回使用する環境は以下の通りで、PostgreSQL 14 から PostgreSQL 18 に移行します。</p>
<table style="height: 155px;" width="724">
<tbody>
<tr>
<td width="283">領域</td>
<td width="283">パス</td>
</tr>
<tr>
<td width="283">旧バージョンの データベースクラスタ</td>
<td width="283">/var/lib/pgsql/14</td>
</tr>
<tr>
<td width="283">新バージョンの データベースクラスタ</td>
<td width="283">/var/lib/pgsql/18</td>
</tr>
<tr>
<td width="283">旧バージョンのPostgreSQLコマンドパス</td>
<td width="283">/usr/local/pgsql14/bin</td>
</tr>
<tr>
<td width="283">新バージョンのPostgreSQLコマンドパス</td>
<td width="283">/usr/local/pgsql18/bin</td>
</tr>
</tbody>
</table>
<p>まず最初に旧バージョンのデータベースを稼働させたまま新データベースクラスタを構築し、旧バージョンでロジカルレプリケーションの有効化とパブリケーションを作成を行います。</p>
<pre>#新しいバージョンのデータベースクラスタを作成して起動
$ /usr/local/pgsql18/bin/initdb -D /var/lib/pgsql/18
[postgres@server1 ~]$ /usr/local/pgsql18/bin/pg_ctl -D /var/lib/pgsql/18 -o "-p 5433" start</pre>
<p>ロジカルレプリケーションではパブリッシャの wal_level は logical である必要があります。ロジカルレプリケーションとは別にストリーミングレプリケーションを利用している場合は既に使用しているレプリケーションスロット数に今回のロジカルレプリケーション用に必要なスロット数を加えた値を max_replication_slots に設定してください。複数のデータベースを新バージョンへ移行する場合は、旧バージョン側でデータベースの数分レプリケーションスロットを作成しますのでその分のスロット数も max_replication_slots に乗じてください。</p>
<p>またパブリッシャから WAL 情報を送信する walsender プロセスの上限を決定する max_wal_senders もレプリケーション接続される数を超えるように設定してください。設定後にサーバーを再起動して設定を反映します。</p>
<pre># ロジカルレプリケーションを利用できるよう旧バージョンの postgresql.conf を編集して再起動
[postgres@server1 ~]$ vi /var/lib/pgsql/14/postgresql.conf
wal_level = logical
#max_replication_slots = 10
#max_wal_senders = 10
[postgres@server1 ~]$ /usr/local/pgsql14/bin/pg_ctl -D /var/lib/pgsql/14 -o "-p 5432" restart</pre>
<p>再起動後、今回のレプリケーションの動作確認用に、旧バージョンのデータベースに users テーブルを作成します。</p>
<pre>[postgres@server1 ~]$ /usr/local/pgsql14/bin/psql -p 5432
psql (14.22)
Type "help" for help.

postgres=# CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE
postgres=# INSERT INTO users(name) VALUES ('taro');
INSERT 0 1
postgres=# INSERT INTO users(name) VALUES ('jiro');
INSERT 0 1
postgres=# \d
List of relations
Schema | Name         | Type     | Owner
-------+--------------+----------+----------
public |    users     |  table   | postgres
public | users_id_seq | sequence | postgres
(2 rows)

postgres=# SELECT * FROM users;
id | name
---+------
1  | taro
2  | jiro
(2 rows)</pre>
<p>その後パブリケーションを作成します。パブリケーションの対象を FOR ALL TABLES とし、すべてのテーブルを同期対象にするようにします。複数データベースを移行する場合はデータベースごとにパブリケーションを作成してください。</p>
<pre>postgres=# CREATE PUBLICATION pub_all FOR ALL TABLES;

# 他データベースも必要であれば同様に作成する
db2=# CREATE PUBLICATION pub_all_2 FOR ALL TABLES;</pre>
<h3 data-section-id="126z3z" data-start="74" data-end="105">旧バージョンデータベースの pg_hba.conf  設定</h3>
<p data-start="107" data-end="165">旧バージョン側  pg_hba.conf には、新バージョンデータベースからのレプリケーション接続を許可する設定を追加します。論理レプリケーションでは、サブスクライバからパブリッシャへ接続してデータ取得を行うため、replication 権限を持つ接続許可が必要です。</p>
<pre data-start="107" data-end="165"># サブスクライバからのレプリケーション接続を許可
host replication postgres 0.0.0.0/0 trust</pre>
<h3>新バージョンに移行するデータベースとスキーマを移行</h3>
<p>ロジカルレプリケーションではテーブルデータのみが同期対象となり、ロール、データベース、スキーマ定義などは自動的には同期されません。そのため、ロジカルレプリケーションを開始する前にこれらを新バージョン側へ移行しておく必要があります。</p>
<p>まずはロールやテーブルスペースなどのグローバルオブジェクトを移行します。</p>
<pre># グローバルオブジェクトをダンプ・リストア
[postgres@server1 ~]$ /usr/local/pgsql18/bin/pg_dumpall -g | /usr/local/pgsql18/bin/psql -p 5433</pre>
<p>次に新バージョンの各データベースに pg_dump -s -C でスキーマ定義を旧バージョンのデータベースからリストアしたのちにサブスクリプションを作成してテーブルデータを同期します。注意点でも述べた通りロジカルレプリケーションではスキーマやテーブル定義といった DDL までは同期されないので別途に pg_dump によって手動でリストアしておく必要があります。</p>
<p>pg_dump, psql は -d で対象データベースを指定します。データベースを複数移行する場合はデータベースごとに pg_dump, psql を実施し、-d で指定するデータベースを変更してください。</p>
<p>pg_dump の結果を psql で実行した後に \d でリレーションを確認すると旧バージョンで作成した users テーブルやシーケンスがコピーされていることが分かります。</p>
<pre>[postgres@server1 ~]$ /usr/local/pgsql18/bin/pg_dump -p 5432 -s -C -d postgres |  /usr/local/pgsql18/bin/psql -p 5433
[postgres@server1 ~]$ /usr/local/pgsql18/bin/psql -p 5433
psql (18.3)
Type "help" for help.
postgres=# \d
List of relations
Schema | Name         | Type     | Owner
-------+--------------+----------+----------
public | users        |  table   | postgres
public | users_id_seq | sequence | postgres
(2 rows)</pre>
<h3>新バージョンの各データベースでのサブスクリプションのセットアップ</h3>
<p>次に旧バージョンの各データベースで作成したパブリケーションに対してサブスクリプションを作成します。サブスクリプションは移行するデータベースごとに作成し、CONNECTION の引数内の dbname や PUBLICATION でしているパブリケーション名は適宜変更してください。</p>
<p>その後テーブルの中身を SELECT するとテーブルデータが同期されていることが分かります。</p>
<pre>postgres=# CREATE SUBSCRIPTION sub_all
CONNECTION 'host=localhost port=5432 dbname=postgres'
PUBLICATION pub_all;
NOTICE: created replication slot "sub_all" on publisher
CREATE SUBSCRIPTION
postgres=# SELECT * FROM users;
id | name
---+------
1  | taro
2  | jiro
(2 rows)</pre>
<h3>旧バージョンの各データベースへの更新を停止して同期の完了を待ち、シーケンス位置を揃える</h3>
<p>サブスクリプション作成後、旧バージョンの各データベースへの更新を一時停止します。これによって旧バージョン側の LSN を止め、新バージョン側の LSN が追い付ける状態にします。</p>
<p>更新処理停止後、新バージョン各データベースごとに pg_stat_subscription 内を確認して received_lsn と latest_end_lsn が一致していることが確認できれば同期は完了です。received_lsn はパブリッシャから受け取った WAL 位置を、latest_end_lsn はパブリッシャから受け取った WAL をサブスクライバで適用し、その完了をパブリッシャに報告した位置を示します。</p>
<pre>postgres=# SELECT * FROM pg_stat_subscription;
-[ RECORD 1 ]---------+------------------------------
subid                 | 16395
subname               | sub_all
worker_type           | apply
pid                   | 3457
leader_pid            |
relid                 |
received_lsn          | 0/1718270
last_msg_send_time    | 2026-04-27 15:33:53.961503+09
last_msg_receipt_time | 2026-04-27 15:33:53.961586+09
latest_end_lsn        | 0/1718270
latest_end_time       | 2026-04-27 15:33:53.961503+09</pre>
<p>その後シーケンス位置を手動で同期します。ロジカルレプリケーションではシーケンス位置はレプリケーションされず、また pg_dump -s でもシーケンス位置を設定する SQL は出力されません。そのためシーケンスの位置は手動で揃える必要があります。</p>
<p>新バージョン側でシーケンスを調整する前の時点ではシーケンスの開始値が初期値である 1 のままとなっています。そのため、新バージョンのデータベース側で INSERT を実行すると、すでにテーブルに存在する id=1 の行と重複し、ユニーク制約違反が発生します。</p>
<pre>postgres=# SELECT currval('users_id_seq');
ERROR: currval of sequence "users_id_seq" is not yet defined in this session
postgres=# INSERT INTO users(name) VALUES ('saburo');
ERROR: duplicate key value violates unique constraint "users_pkey"
DETAIL: Key (id)=(1) already exists.</pre>
<p data-start="140" data-end="199">シーケンス位置は pg_dump の出力に含まれる setval の SQL を新バージョン側の各データベースで実行して反映します。-d オプションの引数もデータベースごとに適宜変更してください。</p>
<pre>[postgres@server1 ~]$ pg_dump -p 5432 -d postgres &gt; dump.sql
[postgres@server1 ~]$ cat dump.sql
(省略)

--
-- Name: users_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
--

SELECT pg_catalog.setval('public.users_id_seq', 2, true);

[postgres@server1 ~]$ /usr/local/pgsql18/bin/psql -p 5433
psql (18.3)
Type "help" for help.
postgres=# SELECT pg_catalog.setval('public.users_id_seq', 2, true);</pre>
<p>その他ラージオブジェクトや拡張機能など、WAL 書き出されずロジカルレプリケーションの対象外となっているものについても手動で同期を行います。これによって旧バージョンと新バージョンの同期は完了です。</p>
<h3>同期完了後アプリケーションの接続先を新バージョンのデータベースに切り替える</h3>
<p>すべてのデータベースの同期完了後にアプリケーションの接続先を切り替えます。</p>
<p>新バージョンの各データベースのサブスクリプションを無効化、マテリアライズドビューをすべて REFRESH したのちに、新バージョン側のpg_hba.conf にアプリケーションからの接続の認証情報を記述し、アプリケーションの接続先を切り替えればアップグレードは完了です。</p>
<pre># サブスクリプションを無効化
postgres=# ALTER SUBSCRIPTION sub_all DISABLE;

# マテリアライズドビューがあれば REFRESH
postgres=# REFRESH MATERIALIZED VIEW my_mv;

# pg_hba.conf にアプリケーションからの接続の認証情報を記載(環境に合わせて適宜記載)
host all application 0.0.0.0/0 trust</pre>
<h2>まとめ</h2>
<p>ロジカルレプリケーションを用いた PostgreSQL のメジャーアップグレードは、適切に設計・運用することで、サービス停止時間を最小限に抑えた安全な移行を実現できます。ただし、データ以外の要素は自動的には同期されないため、スキーマ、シーケンス位置などを含めた包括的な準備が不可欠です。</p>
<p>事前検証と十分な計画を行うことで、本番環境においても安定したアップグレードを実施できます。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Pgpool-II 4.7 の紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgpool/pgpool-4-7/</link>
		
		<dc:creator><![CDATA[越野 太基 (Taiki Koshino)]]></dc:creator>
		<pubDate>Wed, 25 Mar 2026 01:12:44 +0000</pubDate>
				<category><![CDATA[Pgpool-II]]></category>
		<category><![CDATA[OSS]]></category>
		<category><![CDATA[Pgpool-II 4.6]]></category>
		<category><![CDATA[Pgpool-II 4.7]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=19057</guid>

					<description><![CDATA[2025 年 12 月 23 日、Pgpool-II の新しいメジャーバージョン 4.7 がリリースされました。 Pgpool-II 4.7 では、クライアント情報表示機能や、Watchdog と heartbeat r ...]]></description>
										<content:encoded><![CDATA[<p>2025 年 12 月 23 日、Pgpool-II の新しいメジャーバージョン 4.7 がリリースされました。</p>
<p>Pgpool-II 4.7 では、クライアント情報表示機能や、Watchdog と heartbeat receiver のセキュリティ強化、オンラインリカバリの機能が強化されました。また、フロントエンド/バックエンドプロトコルバージョン 3.2 サポートの追加、PostgreSQL 18 への対応も行われました。</p>
<p>Pgpool-II 4.7 の新機能及び変更点は Pgpool-II 公式ドキュメントの以下のページに記載されています。</p>
<p><a href="https://www.pgpool.net/docs/47/ja/html/release-4-7-0.html" target="_blank" rel="noopener">Pgpool-II 4.7 リリースノート</a></p>
<p>本記事では、これらの新機能について詳しく紹介します。</p>
<p><span id="more-19057"></span></p>
<h3>クライアント情報を表示するための pcp_proc_info, show pool_pools の機能強化</h3>
<p>4.6 までは Pgpool-II 経由で PostgreSQL に接続した場合、PostgreSQL 側からは各クライアントの接続情報を確認することができず、Pgpool-II のネットワークアドレスとポート番号のみしかわかりませんでした。<br />
そのため障害が起きてもどのクライアント接続で障害が発生しているのかを調査することが困難でした。</p>
<p>4.7 からは <a href="https://www.pgpool.net/docs/latest/ja/html/pcp-proc-info.html" target="_blank" rel="noopener">pcp_proc_info</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/sql-show-pool-pools.html" target="_blank" rel="noopener">show pool_pools</a> コマンドで Pgpool-II 経由で接続しているクライアントのホスト名、ポート番号、最後に実行した SQL を参照できるようになりました。</p>
<p><span class="PRODUCTNAME">Pgpool-II</span> の子プロセス情報を表示する <a href="https://www.pgpool.net/docs/latest/ja/html/pcp-proc-info.html" target="_blank" rel="noopener">pcp_proc_info</a> コマンドでは client_host(ホスト名), client_port(ポート番号), statement(最後に実行した SQL) が追加されました。</p>
<p>これにより PostgreSQL からでも Pgpool-II 経由で接続しているクライアントの接続情報や最後に実行したクエリ情報を参照できるようになり障害時などに障害が起きているクライアント接続を調査することが容易になりました。</p>
<pre>sraoss@server1:~/setuptest$ pcp_proc_info -p 50001 --verbose
Database : test
Username : sraoss
Start time : 2026-01-08 12:15:18 (0:15 before process restarting)
Client connection count : 1
Major : 3
Minor : 0
Backend connection time : 2026-01-08 12:15:18
Client connection time : 2026-01-08 12:15:18
Client idle duration : 0
Client disconnection time : 2026-01-08 12:16:38
Pool Counter : 1
Backend PID : 20250
Connected : 0
PID : 20195
Backend ID : 0
Status : Wait for connection
Load balance node : 0
client_host : 127.0.0.1
client_port : 54726
statement : SELECT 1;</pre>
<p><span class="PRODUCTNAME">Pgpool-II</span> のコネクションプールの状態を表示する <a href="https://www.pgpool.net/docs/latest/ja/html/sql-show-pool-pools.html" target="_blank" rel="noopener">show pool_pools</a> コマンドにも、client_host(ホスト名), client_port(ポート番号), statement(最後に実行した SQL) が追加されました。</p>
<p>これらの変更で子プロセスやコネクションプーリングの情報とあわせてクライアント情報を参照できるようになりました。</p>
<pre class="PROGRAMLISTING">test=# show pool_pools;
 pool_pid |                      start_time                      | client_connection_count | pool_id | backend_id | database | username | backend_connection_time | client_connection_time | client_disconnection_time | client_idle_duration | majorversion | minorversion | pool_counter | pool_backendpid | pool_connected |       status        | load_balance_node |  client_host  | client_port |  statement  
----------+------------------------------------------------------+-------------------------+---------+------------+----------+----------+-------------------------+------------------------+---------------------------+----------------------+--------------+--------------+--------------+-----------------+----------------+---------------------+-------------------+---------------+-------------+-------------
[snip]
 1336537  | 2025-06-24 10:53:35                                  | 0                       | 0       | 0          | test     |  sraoss  | 2025-06-24 10:55:58     | 2025-06-24 10:55:59    |                           | 0                    | 3            | 0            | 1            | 1336703         | 1              | Idle                | 0                 | 192.168.10.11 | 39216       | 
 1336537  | 2025-06-24 10:53:35                                  | 0                       | 0       | 1          | test     |  sraoss  | 2025-06-24 10:55:58     | 2025-06-24 10:55:59    |                           | 0                    | 3            | 0            | 1            | 1336704         | 1              | Idle                | 1                 | 192.168.10.11 | 39216       | select 1;
 1336537  | 2025-06-24 10:53:35                                  | 0                       | 1       | 0          |          |          |                         |                        |                           | 0                    | 0            | 0            | 0            | 0               | 0              | Idle                | 0                 | 192.168.10.11 | 39216       | 
 1336537  | 2025-06-24 10:53:35                                  | 0                       | 1       | 1          |          |          |                         |                        |                           | 0                    | 0            | 0            | 0            | 0               | 0              | Idle                | 0                 | 192.168.10.11 | 39216       | select 1;</pre>
<h3>pgpool_adm_pcp_proc_info 関数の追加</h3>
<p>pgpool_adm エクステンションに、Pgpool-II の子プロセスの情報を表示する <a href="https://www.pgpool.net/docs/latest/ja/html/pgpool-adm-pcp-proc-info.html" target="_blank" rel="noopener">pgool_adm_pcp_proc_info</a> 関数が追加されました。 pgpool_adm エクステンションは Pgpool-II 経由でも、あるいは直接 PostgreSQL から呼び出せる関数群です。</p>
<p><a href="https://www.pgpool.net/docs/latest/ja/html/pgpool-adm-pcp-proc-info.html" target="_blank" rel="noopener">pgool_adm_pcp_proc_info</a> で表示される情報は pcp_proc_info コマンドと同様ですが、pgpool_adm エクステンションの関数であるため 、PostgreSQL クライアントからでも呼び出せます。</p>
<p>pgpool_adm を使うメリットは、SQLが使用でき WHERE 句で条件を指定して表示内容を絞り込むことができることです。(pcp コマンドの場合は、出力結果を整形するために OS のコマンドを併用する必要があります。)</p>
<p>導入には以下コマンドで各サーバーで pgpool_adm をインストールしてください。</p>
<pre class="PROGRAMLISTING"># 各サーバーで以下を実行してインストール 
$ psql test
test=# CREATE EXTENSION pgpool_adm;</pre>
<p>その後 Pgpool-II や PostgreSQL のクライアント上で <a href="https://www.pgpool.net/docs/latest/ja/html/pgpool-adm-pcp-proc-info.html" target="_blank" rel="noopener">pgpool_adm_pcp_proc_info</a> を実行します。<br />
connected 列は接続状況を表示(0=接続なし, 1=接続中) しており、今回の例のように WHERE 句に &#8220;connected = 1&#8221; を指定することで接続中の情報に絞ることもできます。</p>
<pre class="PROGRAMLISTING">test=# select * from pcp_proc_info(host =&gt; '', port =&gt; 11001, username =&gt; 'sraoss', password =&gt; 'sraoss') where connected = '1';
-[ RECORD 1 ]-------------+----------------------------------------------------------------------------------------------------------------------------
database                  | test
username                  | sraoss
start_time                | 2026-01-08 10:56:08
client_connection_count   | 0
major                     | 3
minor                     | 0
backend_connection_time   | 2026-01-08 10:58:37
client_connection_time    | 2026-01-08 10:58:37
client_idle_duration      | 0
client_disconnection_time | 
pool_counter              | 1
backend_pid               | 14750
connected                 | 1
pid                       | 14585
backend_id                | 0
status                    | Execute command
load_balance_node         | 1
client_host               | 127.0.0.1
client_port               | 59120
statement                 | select * from pcp_proc_info(host =&gt; '', port =&gt; 11001, username =&gt; 'sraoss', password =&gt; 'sraoss') where connected = '1';</pre>
<p>また pg_stat_activity と組み合わせてより詳細な情報を表示することも可能です。<br />
以下の SQL では <a href="https://www.pgpool.net/docs/latest/ja/html/pgpool-adm-pcp-proc-info.html" target="_blank" rel="noopener">pgpool_adm_pcp_proc_info</a> とpg_stat_activity を結合して <a href="https://www.pgpool.net/docs/latest/ja/html/pgpool-adm-pcp-proc-info.html" target="_blank" rel="noopener">pgool_adm_pcp_proc_info</a> では取得できない state を pg_stat_activity をから取得しています。<br />
他にも wait_event など pg_stat_activity にしかない情報も同時に取得するなど要件に応じてクライアント情報を取得できます。</p>
<pre>test=# SELECT p.username, p.database, p.client_port, s.state, s.wait_event, s.query,
              p.pid as pgpool_pid, s.pid as backend_pid
              FROM pcp_proc_info(host =&gt; '', port =&gt; 11001,
                                 username =&gt; 'sraoss', password =&gt; 'sraoss') AS p
              JOIN pg_stat_activity AS s ON s.pid::text = p.backend_pid;
-[ RECORD 1 ]-------------+----------------------------------------------------------------------------------------------------------------------------
username                  | sraoss
 database                 |  test
 client_host              | 192.168.100.101
client_port               | 50001
state                     | active  
query                     | select 1;
pgpool_pid                | 21467
backend_pid               | 21500</pre>
<h3>ライフチェックログの改善</h3>
<p>ライフチェックが開始したとき Watchdog は ライフチェックが開始したことを知らせるログを出力します。<br />
4.6 までは正常に開始したタイミングでしかログが出力されないため、正常に動作しているかを確認するために開始ログが出るまでログを監視する必要があり、またライフチェックが正常に開始していない状況に気づくのが困難でした。</p>
<pre>LOG:  watchdog: lifecheck started</pre>
<p>4.7 からはライフチェックが開始されるまで定期的にライフチェックが開始していない警告を出力するようになり、ライフチェック開始までログファイルを監視する必要がなくなりました。<br />
間隔は wd_interval × 10 秒です。</p>
<pre><i>WARNING:  watchdog: lifecheck has not started yet</i></pre>
<h3>Watchdog と heartbeat receiver のセキュリティ強化</h3>
<p>Watchdog と heartbeat receiver が受け付けるアドレスを制限することができるようになりました。</p>
<p>4.6 まではいずれのプロセスも、ホストが持つすべてのネットワークアドレスへの接続を受け付けていました。</p>
<pre>tcp        0      0 <b>0.0.0.0:9000</b>            0.0.0.0:*     LISTEN   3583037/pgpool: watchdog
Tcp6       0      0 <b>:::9000                 </b>:::*          LISTEN   3583037/pgpool: watchdog
Udp        0      0 <b>0.0.0.0:9694</b>            0.0.0.0:*              3583050/pgpool: heartbeat receiver
udp        0      0 <b>0.0.0.0:9694</b>            0.0.0.0:*              3583044/pgpool: heartbeat receiver
udp6       0      0 <b>:::9694                 </b>:::*                   3583044/pgpool: heartbeat receiver
udp6       0      0 <b>:::9694                 </b>:::*                   3583050/pgpool: heartbeat receiver</pre>
<p>4.7 からはセキュリティ上の点から <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HOSTNAME" target="_blank" rel="noopener">hostname</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HEARTBEAT-HOSTNAME" target="_blank" rel="noopener">heartbeat_hostname</a> で指定したネットワークアドレスへのみ接続を受け付けるようになりました。</p>
<pre># pgpool.conf 設定例
hostname0 = '192.168.100.50'
wd_port0 = 9000
heartbeat_hostname0 = '192.168.100.101'
heartbeat_port0 = 9694
hostname1 = '192.168.100.60'
wd_port0 = 9000
heartbeat_hostname1 = '192.168.100.102'
heartbeat_port1 = 9694
hostname2 = '192.168.100.70'
wd_port0 = 9000
heartbeat_hostname2 = '192.168.100.103'
heartbeat_port2 = 9694</pre>
<pre>tcp        0      0 <b>192.168.100.50:</b><b>9000</b><b>    </b>0.0.0.0:*     LISTEN      41636/pgpool: watchdog
tcp        0      0 <b>192.168.100.50:</b><b>9000</b><b>    </b>0.0.0.0:*     LISTEN      41638/pgpool: watchdog
udp        0      0 <b>192.168.100.101:9694 </b>  0.0.0.0:*                 41649/pgpool: heartbeat receiver
udp        0      0 <b>192.168.100.101:9694</b>   0.0.0.0:*                 41650/pgpool: heartbeat receiver</pre>
<p>もし他ノードから <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HOSTNAME" target="_blank" rel="noopener">hostname</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HEARTBEAT-HOSTNAME" target="_blank" rel="noopener">heartbeat_hostname</a> で指定したネットワークアドレス以外へ heartbeat を送る設定とすると以下メッセージのように lifecheck に失敗します。<br />
4.7 へ移行する場合は <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HOSTNAME" target="_blank" rel="noopener">hostname</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HEARTBEAT-HOSTNAME" target="_blank" rel="noopener">heartbeat_hostname</a> で watchdog と heartbeat で LISTEN するソケットを設定し、他ノードから heartbeat を送るソケットを <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HOSTNAME" target="_blank" rel="noopener">hostname</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HEARTBEAT-HOSTNAME" target="_blank" rel="noopener">heatbeat_hostname</a> で指定したネットワークアドレスとしてください。</p>
<pre>WARNING:  watchdog: lifecheck has not started yet</pre>
<p>また 4.7. 1 ではさらに Watchdog と heartbeat それぞれについて LISTEN するソケットを個別で指定できるようになりました。<br />
これによりノード外部から見えるアドレスと、ノード内部から認識されるアドレスが異なる可能性があるコンテナ環境や、ポートフォワーディングを設定している場合でも、より柔軟に設定できるようになりました。<br />
Watchdog については <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-WD-LISTEN-ADDRESS" target="_blank" rel="noopener">wd_listen_address</a> によってネットワークアドレスを、<a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-WD-LISTEN-PORT" target="_blank" rel="noopener">wd_listen_port</a> によってポートも指定することができます。<br />
heartbeat についてはそれぞれ <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-WD-HEARTBEAT-LISTEN-ADDRESSES" target="_blank" rel="noopener">wd_heartbeat_listen_addresses</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-WD-HEARTBEAT-LISTEN-PORT" target="_blank" rel="noopener">wd_heartbeat_listen_port</a> によって指定できます。<br />
これらのパラメータが設定されているとき <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HOSTNAME" target="_blank" rel="noopener">hostname</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HEARTBEAT-HOSTNAME" target="_blank" rel="noopener">heartbeat_hostname</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-WD-PORT" target="_blank" rel="noopener">wd_port</a>, <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-watchdog-config.html#GUC-HEARTBEAT-PORT" target="_blank" rel="noopener">heartbeat_port</a> のローカルの設定は上書きされてソケットが作成されます。</p>
<pre># pgpool.conf 設定例
hostname0 = '192.168.100.50'
wd_port0 = 9000
heartbeat_hostname0 = '192.168.100.101'
heartbeat_port0 = 9694
wd_listen_address = 192.168.100.100
wd_listen_port = 50000
wd_heartbeat_listen_addresses = 102.168.100.110
wd_heartbeat_listen_port = 51000</pre>
<pre>tcp        0      0 <b>192.168.100.100:50000    </b>0.0.0.0:*     LISTEN      41636/pgpool: watchdog
udp        0      0 <b>192.168.100.110:51000 </b>   0.0.0.0:*                 41649/pgpool: heartbeat receiver
udp        0      0 <b>192.168.100.110:51000</b>    0.0.0.0:*                 41650/pgpool: heartbeat receiver</pre>
<p>これらのパラメータが導入された背景は、Docker 環境を代表とした TCP 転送ルールを設けているインターフェース間で通信をする際に LISTEN するソケットを転送ルールに合わせて設定したいケースに対応するためです。<br />
例えばノード 0 が IP:192.168.0.0, ポート番号:10000 のソケットに接続しようとし、TCP 転送ルールによってノード 1 の IP:192.168.100.100,ポート番号:20000 のソケットにリダイレクトされる環境の場合、ノード 1 側でリダイレクト後のネットワークアドレス、ポート番号(今回の例では IP:192.168.100.100, ポート番号:20000)に設定することで TCP 転送ルールがある場合でも通信が可能となりました。</p>
<h3>オンラインリカバリに使用するデータベースを指定する recovery_database パラメータの追加</h3>
<p>オンラインリカバリとは障害が発生して切り離されてしまった PostgreSQL ノードをプライマリに再同期して復帰する処理を各ノードを停止することなく行うことができる機能です。</p>
<p>以前はオンラインリカバリに template1 データベースを使用するようにしていましたが、今回追加された <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-online-recovery.html#GUC-RECOVERY-DATABASE" target="_blank" rel="noopener">recovery_databse</a> パラメータにオンラインリカバリに使用するデータベースを指定することができるようになりました。</p>
<pre>#pgpool.conf の recovery_database を指定
recovery_database = 'postgres'</pre>
<p>デフォルト値は postgres になっています。<br />
4.6 以前から移行をする際には <a href="https://www.pgpool.net/docs/latest/ja/html/runtime-online-recovery.html#GUC-RECOVERY-DATABASE" target="_blank" rel="noopener">recovery_database</a> に指定したデータベースで下記コマンドを実施してオンラインリカバリに必要な関数をインストールしておく必要があります。</p>
<pre class="PROGRAMLISTING">psql postgres -c "CREATE EXTENSION pgpool_recovery"</pre>
<h3><tt class="FILENAME">.pcppass</tt>ファイルからの読み取りに失敗時の挙動改善</h3>
<p>.pcppass ファイルは pcp コマンドを実行したときに読み込まれるパスワードファイルです。</p>
<p>4.6 までは pcp コマンド実行時に .pcppass ファイルが未作成かパスワードファイルの権限設定が不適切の場合、エラーで終了していました。<br />
また -d, &#8211;debug オプションがないとデバッグ情報が出力されず失敗の原因も特定できませんでした。</p>
<pre>FATAL:  authentication failed for user "sraoss"
DETAIL:  username and/or password does not match</pre>
<p>失敗後は .pcppass ファイルを適切な権限で作成するか、パスワード入力を受け付けるオプションである -W オプションをつけて pcp コマンドを再実行する必要がありました。</p>
<pre>pcp_node_info -p 9898 -W
Password:</pre>
<p>4.7 からはエラーを出力して終了するのではなく、クライアントのコマンドプロンプトにフォールバックして引き続きパスワードを入力することができるようになりました。</p>
<p>また WARNING による警告が -d, &#8211;debug オプションなく出力される仕様に変更され、読み取りができなかった原因もメッセージから特定することができます。</p>
<pre class="PROGRAMLISTING">WARNING: password file ~/.pcppass is not a plain file
WARNING: password file ~/.pcppass has group or world access; permissions should be u=rw (0600) or less</pre>
<h3>フロントエンド / バックエンドプロトコルバージョン 3.2 サポートの追加</h3>
<p>PostgreSQL 18 ではプロトコルバージョン 3.2 に対応し、可変長のキャンセルキーが用いることができるようになりました。<br />
この変更に合わせ、Pgpool-II でもプロトコルバージョン 3.2 を利用できるように改善がされました。</p>
<p>max_protocol_version や PGMAXPROTOCOLVERSION を用いた以下のようなコマンドで 3.2 プロトコルを使用して PostgreSQL のフロントエンドとバックエンドを接続することができます。<br />
バージョンには 3.2 だけでなく PostgreSQL 18 のデフォルトのプロトコルバージョンである 3.0 を指定することもできます。</p>
<pre class="PROGRAMLISTING"># max_protocol_version オプションで 3.0 バージョンで接続
psql "host=localhost dbname=test user=sraoss max_protocol_version=3.0 port=11000"

# 環境変数 PGMAXPROTOCOLVERSION に 3.2 を指定して接続
PGMAXPROTOCOLVERSION="3.2" psql -p 11000 test</pre>
<p>新規接続時は指定したプロトコルバージョンで接続を確立しますが、コネクションプーリングのキャッシュがある場合は既存のキャッシュに保存されたのプロトコルバージョンを用いて接続を行うため確立済みの接続間でバージョンが異なることによるエラーの心配もありません。</p>
<h3>PostgreSQL 18 の SQL パーサの導入</h3>
<p>Pgpool-II ではメジャーリリースするたびに、PostgreSQL の最新パーサを移植しています。今回のリリースでは PostgreSQL 18 の新しいパーサを取り込みました。</p>
<p>Pgpool-II の負荷分散機能では、SQL を解析して参照か更新かを判別し、どのノードに振り分けるかを決めています。そのため、PostgreSQL の新バージョンでの SQL の変更に対応するには、SQL パーサを移植する必要があります。</p>
<p>PostgreSQL 18 での SQL のおもな変更点は以下のとおりです。</p>
<ul>
<li>生成列を仮想列として使用可能に</li>
<li>DML クエリの RETURNING にOLD/NEWのサポートを追加</li>
<li>各種制約の追加(例: WITHOUT OVERLAPS、ENFORCED/NOT ENFORCED)</li>
</ul>
<p>Pgpool-II 4.7 では上記の変更点に対応しています。</p>
<h3>logdir パラメータ名を work_dir へ変更</h3>
<p><tt>4.6 までは Pgpool-II の起動状態を記述する </tt><tt class="LITERAL">pgpool_status や memq_lock_file といった管理</tt>ファイルを logdir に指定するディレクトリに保存していました。<br />
しかし logdir というパラメータ名はログ関連のファイルを格納するディレクトリの設定パラメータと誤解されやすい問題がありました。</p>
<p>4.7 からはパラメータ名が <a href="https://www.pgpool.net/docs/47/ja/html/runtime-misc.html#GUC-WORK-DIR" target="_blank" rel="noopener">work_dir</a> へ変更となりました。</p>
<p>logdir のパラメータ自体も引き続き利用することができ、logdir に指定した値が <a href="https://www.pgpool.net/docs/47/ja/html/runtime-misc.html#GUC-WORK-DIR" target="_blank" rel="noopener">work_dir</a> の設定値へと再設定され Pgpool-II の終了時に以下ワーニングが表示されます。</p>
<pre>2026-01-08 11:50:48.193: main pid 18667: WARNING: logdir is changed to work_dir
2026-01-08 11:50:48.193: main pid 18667: DETAIL: if logdir is specified, the value will be set to work_dir</pre>
<h3>Slony モードの廃止</h3>
<p class="PROGRAMLISTING"><a href="https://www.pgpool.net/docs/latest/ja/html/runtime-config-running-mode.html#GUC-BACKEND-CLUSTERING-MODE" target="_blank" rel="noopener">backend_clustering_mode</a> で指定することができていた Slony モードが廃止されました。</p>
<p class="PROGRAMLISTING">データのレプリケーションを Slony-I が行うクラスタリングモードの一つでしたが、Slony-I は 3 年前からリリースが停止しています。<br />
現在は Slony モードについて積極的に利用するユーザーが見られず、廃止のアナウンスに異議がなかったため 4.7 からは廃止となりました。</p>
<h3>Pgpool-II の libpcp ライブラリの名称を libpgpoolpcp に変更</h3>
<p class="PROGRAMLISTING">4.7.1 のマイナリリースにて Pgpool-II のライブラリである libpcp の名称を libpgpoolpcp に変更されました。<br />
背景として、RHEL の libpcp ライブラリと Pgpool-II の libpcp ライブラリがコンフリクトする問題があったためです。</p>
<h2>おわりに</h2>
<p>今回は、Pgpool-II 4.7 の新機能について紹介しました。</p>
<p>Pgpool-II 4.7 では、より実用的で便利な機能が数多く追加・改善されています。PostgreSQL の高可用性構成や負荷分散の実現を検討されている方にとって、Pgpool-II は有力な選択肢です。ぜひこの機会に Pgpool-II の導入をご検討ください。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PostgreSQL 17 増分バックアップの実践活用と運用上の考慮点</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/postgresql17-incremental-backup-guide/</link>
		
		<dc:creator><![CDATA[越野 太基 (Taiki Koshino)]]></dc:creator>
		<pubDate>Tue, 16 Dec 2025 05:00:10 +0000</pubDate>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[PostgreSQL 17]]></category>
		<category><![CDATA[バックアップ]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=18967</guid>

					<description><![CDATA[この記事は SRA Advent Calendar 2025 18 日目の記事です。 PostgreSQL には様々なバックアップの方法が提供されています。 それぞれのバックアップの方法は利点が違い、運用方法も手順も異な ...]]></description>
										<content:encoded><![CDATA[<p>この記事は <a href="https://qiita.com/advent-calendar/2025/sra" target="_blank" rel="noopener">SRA Advent Calendar 2025</a> 18 日目の記事です。</p>
<p>PostgreSQL には様々なバックアップの方法が提供されています。<br />
それぞれのバックアップの方法は利点が違い、運用方法も手順も異なります。<br />
今回はバックアップ方法の簡単なおさらいと、PostgreSQL 17 で標準機能として追加された増分バックアップについて紹介します。</p>
<p><span id="more-18967"></span></p>
<h1>PostgreSQLのバックアップの種類</h1>
<p>PostgreSQL のバックアップは大きく論理バックアップ と 物理バックアップの 2 種類に分類できます。</p>
<h2>論理バックアップ</h2>
<p>SQL レベルでデータを取得する方式です。<br data-start="855" data-end="858" />CREATE TABLE や INSERT 文などで現在のデータベースの状態を再現できるファイルを生成します。<br data-start="917" data-end="920" />異なるOSアーキテクチャ間や PostgreSQL メジャーバージョン間でもリストア可能という柔軟性が大きな利点です。</p>
<h2>物理バックアップ</h2>
<p>データベースクラスタ全体のディレクトリを丸ごと保存する方式です。<br data-start="1018" data-end="1021" />Linux の cp コマンドや PostgreSQL 標準ツールである pg_basebackup を利用できます。<br data-start="1084" data-end="1087" />pg_basebackup では PITR（Point-In-Time Recovery）や PostgreSQL 17 で追加された 増分バックアップ を利用できる点が最大の特徴です。</p>
<p>今回は、この「増分バックアップ」について詳しく紹介します。</p>
<h1>増分バックアップとメリット</h1>
<p><img decoding="async" class="alignnone wp-image-19195" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201-300x168.png" alt="" width="637" height="357" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201-300x168.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201-1024x575.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201-768x431.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201-304x171.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201-282x158.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/dd52debf533c5c5cea3a99fcffb0e201.png 1364w" sizes="(max-width: 637px) 100vw, 637px" /></p>
<p>増分バックアップは、ある時点で取得したフルバックアップをベースとし、その後に変更された部分だけを保存する方式です。</p>
<p data-start="530" data-end="614">たとえば、10 TB のデータベースを毎日 30 日分フルバックアップで保存すると、<br data-start="572" data-end="575" />10 TB × 30 日 = 300 TB もの容量が必要になります。</p>
<p data-start="616" data-end="686">しかし増分バックアップであれば、<br data-start="632" data-end="635" />初日のフル 10 TB + 毎日の変更分のみを保存すればよく、大幅なストレージ削減が可能です。<br />
上記の図は毎日の変更分を10GBと想定した場合の比較図となります。</p>
<p data-start="688" data-end="801">また、バックアップ取得時間も短縮できます。<br />
フルバックアップではすべてのデータをコピーするため時間がかかりますが、増分バックアップは変更分だけを取得するためバックアップ時間の短縮につながります。<br />
また結果としてサーバー負荷の軽減にも寄与します。</p>
<h1>増分バックアップの手順</h1>
<p data-start="824" data-end="936">従来、PostgreSQL で増分バックアップを行いたい場合は、サードパーティツールである pg_rman の利用が一般的でした。<br data-start="896" data-end="899" />ただし、pg_rman は Windows 非対応という課題がありました。</p>
<p data-start="938" data-end="1010">PostgreSQL 17 ではこれらの問題が解消され、標準機能として増分バックアップがサポートされました。<br data-start="991" data-end="994" />主な追加項目は以下のとおりです。</p>
<ol>
<li>pg_basebackup に増分バックアップを取得する -​-incremental オプションが追加</li>
<li>フルバックアップと増分バックアップを統合する pg_combinebackup コマンドの追加</li>
<li>増分バックアップの制御にかかわる summarize_wal, wal_keep_summary パラメータの追加</li>
</ol>
<p>これらによって増分バックアップの取得が可能になっています。<br />
それぞれのコマンドやパラメータの扱い方について詳しく見ていきましょう。</p>
<p>動作確認環境と postgresql.conf のパラメータは以下です。</p>
<p><strong>動作環境</strong></p>
<table width="1218">
<tbody>
<tr>
<td width="406"><b>領域</b></td>
<td width="406"><b>パス</b></td>
<td width="406"><b>備考</b></td>
</tr>
<tr>
<td width="406">データベースクラスタ</td>
<td width="406">data</td>
<td width="406"></td>
</tr>
<tr>
<td width="406">WAL領域</td>
<td width="406">data/pg_wal</td>
<td width="406"></td>
</tr>
<tr>
<td width="406">バックアップ格納先</td>
<td width="406">backup</td>
<td width="406">フルバックアップ、<br />
増分バックアップを保存</td>
</tr>
</tbody>
</table>
<p><strong>postgresql.conf パラメータ</strong></p>
<table width="1218">
<tbody>
<tr>
<td width="406"><b>パラメータ名</b></td>
<td width="406"><b>設定値</b></td>
<td width="406"><b>備考</b></td>
</tr>
<tr>
<td width="406">summarize_wal</td>
<td width="406">on(off がデフォルト)</td>
<td width="406">on でないと<br />
増分バックアップ不可</td>
</tr>
<tr>
<td width="406">wal_level</td>
<td width="406">replica(デフォルト) 以上</td>
<td width="406">summarize_wal が on の時は replica 以上が必須</td>
</tr>
</tbody>
</table>
<h2>増分バックアップのコマンド</h2>
<p>増分バックアップの手順は大きく分けて以下です。</p>
<ol>
<li>pg_basebackup によるフルバックアップの取得</li>
<li>pg_basebackup -​-incremental による増分バックアップの取得</li>
<li>pg_combinebackup によるフルバックアップと増分バックアップの統合</li>
</ol>
<p>コマンド実行例をもとに見ていきましょう。</p>
<p>フルバックアップ取得前の時点では full_backup というテーブルがあるのみです。</p>
<p>これから各増分バックアップ取得時点でテーブルを追加していき、各世代のバックアップの状態にリストアできるかを見ていきます。</p>
<pre>$ psql
psql (17.6)
"help"でヘルプを表示します。
postgres=# \d
               リレーション一覧
 スキーマ |    名前     |  タイプ  |  所有者
----------+-------------+----------+----------
 public   | full_backup | テーブル | postgres
(1 行)</pre>
<p>最初に pg_basebackup コマンドでフルバックアップを取得します。</p>
<pre># -P オプションでサイズや進捗を確認可能
$ pg_basebackup  -D backup/full -P
23818/23818 kB (100%), 1/1 テーブル空間</pre>
<p>その後 inc1 テーブルを作成し、一回目の増分バックアップを取得します。</p>
<p>ここで pg_basebackup に新規で追加された -​-incremental オプションを用います。<br />
引数には前回取得したバックアップ、つまりフルバックアップの backup_manifest ファイルを指定します。<br />
backup_manifest ファイルはバックアップのトップディレクトリにあるのでそちらのパスを指定してください。</p>
<pre>postgres=# create table inc1 (i int);
CREATE TABLE
$ pg_basebackup --incremental=backup/full/backup_manifest -D backup/inc1</pre>
<p>二回目の増分バックアップも同様に inc2 テーブルを作成後取得します。</p>
<p>この時注意が必要なのが前回のバックアップを指定することです。<br />
今回だとフルバックアップではなく一回目の増分バックアップの backup_manifest を指定します。</p>
<pre>postgres=# create table inc2 (i int);
CREATE TABLE
$ pg_basebackup --incremental=backup/inc1/backup_manifest -D backup/inc2</pre>
<p>最後に pg_combinebackup で各世代を統合していきます。<br />
pg_combinebackup の -o オプションでは統合バックアップの出力先を指定し、その後の引数はフルバックアップから統合したい世代までの増分バックアップをすべて指定します。</p>
<p>統合後はpg_verifybackupでバックアップの整合性も忘れずチェックするようにしてください。</p>
<pre># フルバックアップからinc1(inc1 テーブルがある時点)まで
$ pg_combinebackup -o backup/combine_full_inc1 backup/full/ backup/inc1
# フルバックアップからinc2(inc1, inc2 テーブルがある時点)まで
$ pg_combinebackup -o backup/combine_full_inc2 backup/full/ backup/inc1 backup/inc2/
# 各統合バックアップを pg_verifybackup で検証
$ pg_verifybackup backup/combine_full_inc1
バックアップが正常に検証されました
$ pg_verifybackup backup/combine_full_inc2
バックアップが正常に検証されました</pre>
<h2>各世代増分バックアップの中身を確認</h2>
<p data-start="97" data-end="132">では、各世代のバックアップが正しく取得できているか確認してみましょう。</p>
<p data-start="134" data-end="235">統合バックアップを、それぞれ異なる port 番号 に設定して起動すると、各世代におけるinc1、inc2テーブルの状態が、作成時点の内容として保持されていることが分かります。</p>
<p data-start="237" data-end="283">この検証により、全ての世代でバックアップが正しく取得されていることを確認できました。</p>
<pre>$ pg_ctl -o "-p 5433" start -D backup/combine_full_inc1/
$ psql –p 5433
postgres=# \d
               リレーション一覧
 スキーマ |    名前     |  タイプ  |  所有者
----------+-------------+----------+----------
 public   | full_backup | テーブル | postgres
 public   | inc1        | テーブル | postgres
$ pg_ctl -o "-p 5434" start -D backup/combine_full_inc2/
$ psql –p 5434
postgres=# \d
               リレーション一覧
 スキーマ |    名前     |  タイプ  |  所有者
----------+-------------+----------+----------
 public   | full_backup | テーブル | postgres
 public   | inc1        | テーブル | postgres
 public   | inc2        | テーブル | postgres</pre>
<h2>増分バックアップのストレージコストと取得時間</h2>
<p data-start="100" data-end="190">最初に挙げたメリットとして、ストレージコストとバックアップ取得時間を抑えられる点がありました。<br data-start="158" data-end="161" />ここでは、実際にどの程度削減できているのか確認してみます。</p>
<p data-start="192" data-end="307">まずストレージ使用量を比較すると、初回に取得したフルバックアップは 888 MB と比較的大きなサイズでした。<br data-start="251" data-end="254" />一方、続いて取得した増分バックアップは どれも約 4 MB 程度 と非常に小さく抑えられています。</p>
<p data-start="309" data-end="439">これを「すべての世代をフルバックアップで保存する場合」と比べてみると、毎回 888 MB 近く消費することになります。<br data-start="367" data-end="370" />それに対して増分バックアップは変更分のみを保存すればよいため、世代を重ねてもバックアップ容量を大幅に抑えられる ことが分かります。</p>
<pre>$ du -h  --max-depth=1 backup/
888M     backup/full
6M     backup/inc1
4M     backup/inc2</pre>
<p>また time コマンドでバックアップ取得の時間も比べてみましょう。</p>
<p>pg_basebackup -​-incremental と -​-incremental オプションなしのフルバックアップの取得時間を比べてみると、-​-incremental での増分バックアップは取得時間がかなり短いことが分かります。</p>
<pre>$ time pg_basebackup -D backup/inc_3 --incremental=backup/inc2/backup_manifest -c fast -P
  4045/888986 kB (100%), 1/1 テーブル空間
real    0m4.391s
$ time pg_basebackup -D backup/full_3 -c fast -P
888986/888986 kB (100%), 1/1 テーブル空間
real    0m32.777s</pre>
<h2>pg_combinebackup のオプション</h2>
<p>pg_combinebackup には統合のファイルコピーを高速化するオプションが用意されています。</p>
<p><strong>ファイルコピーを高速化するオプション</strong></p>
<table width="1441">
<tbody>
<tr>
<td width="273"><b>オプション</b></td>
<td width="395"><b>説明</b></td>
<td width="413"><b>環境</b></td>
<td width="360"><b>メリット</b></td>
</tr>
<tr>
<td width="273">-​-copy</td>
<td width="395">ファイルをコピー<br />
[デフォルト]</td>
<td width="413"></td>
<td width="360"></td>
</tr>
<tr>
<td width="273">-​-copy-file-range</td>
<td width="395">copy_file_rangeを利用したファイル部分コピー</td>
<td width="413">FreeBSDか<br />
カーネル4.5+の Linux</td>
<td width="360">カーネル空間で<br />
完結するため高速</td>
</tr>
<tr>
<td width="273">-​-clone</td>
<td width="395">Reflink機能での<br />
ファイルクローンコピー</td>
<td width="413">カーネル 4.5+の Linux の<br />
Btrfs、Reflinkが有効なXFS<br />
macOS の APFS</td>
<td width="360">Inodeとブロックマップコピーのみのため高速</td>
</tr>
<tr>
<td width="273">-k, -​-link(v18で追加)</td>
<td width="395">ハードリンクを作成する<br />
コピー</td>
<td width="413"></td>
<td width="360">リンク作成のみのため<br />
高速</td>
</tr>
</tbody>
</table>
<p>デフォルトのオプション以外はすべて高速化できるものの、すべて入出力のディレクトリが同じファイルシステムである必要がある点には注意してください。<br />
-​-copy-file-range, -​-clone については実行できる環境に上記表のような制限もあります。</p>
<p><strong>同期のオプション</strong></p>
<table width="1361">
<tbody>
<tr>
<td width="303"><b>オプション</b></td>
<td width="650"><b>バックアップ統合の対象</b></td>
<td width="408"><b>メリット</b></td>
</tr>
<tr>
<td width="303">-​-fsync</td>
<td width="650">バックアップディレクトリ内全ファイル<br />
[デフォルト]</td>
<td width="408">最小限のバックアップで済む</td>
</tr>
<tr>
<td width="303">-​-plain</td>
<td width="650">WALファイルとテーブル空間全体の<br />
シンボリックリンクまで</td>
<td width="408">左記をバックアップに含められる</td>
</tr>
<tr>
<td width="303">-​-syncfs</td>
<td width="650">バックアップディレクトリを含む<br />
ファイルシステム全体</td>
<td width="408">ファイル一つ一つを開かないため統合が早い</td>
</tr>
</tbody>
</table>
<p>同期する範囲を指定できるオプションもあり、<br data-start="202" data-end="205" />同期対象を増やすほどディスクへの書き込みがより確実に行われるようになります。</p>
<p>デフォルトではバックアップ対象のディレクトリのみですが、-​-plain で WAL ファイルとテーブル空間全体のシンボリックリンクまで、-​-syncfs ではバックアップディレクトリを含むファイルシステム全体を同期の対象とできます。</p>
<p>-​-syncfs はファイルを一つ一つ開かず同期をチェックするため同期が素早く完了できるというメリットもあります。</p>
<h2>増分バックアップ使用上の注意点</h2>
<p>注意点は大きく分けて以下の3つです。それぞれ見ていきます。</p>
<ol>
<li>パラメータの管理</li>
<li>フルバックアップ～増分バックアップの保存</li>
<li>ストレージ容量</li>
</ol>
<h3>パラメータの管理</h3>
<p>増分バックアップで管理すべきパラメータは以下です。</p>
<ol>
<li>summarize_wal</li>
<li>wal_level</li>
<li>wal_summary_keep_time</li>
</ol>
<p>summarize_wal は pg_basebackup -​-incremental をする際に参照する wal の情報をまとめたサマリファイルを作成するか否かを制御するパラメータです。</p>
<p>このファイルがない状態で増分バックアップを取得しようとするとエラーとなり取得に失敗してしまいます。<br />
デフォルトでは off となっていますので忘れずに on としてください。</p>
<pre># summarize_wal が off で取得したフルバックアップを対象とするとエラー
$ pg_basebackup --incremental=backup/full/backup_manifest -D backup/inc1
pg_basebackup: エラー: ベースバックアップを開始できませんでした: 
ERROR:  WAL集約が有効でなければ差分バックアップは取得できません</pre>
<p>wal_level についても replica 以上が必要です。<br />
これが replica 以上でないと summarize_wal のパラメータが無効となる仕様となっています。</p>
<p>wal_summary_keep_time はサマリファイルを保存する期間を指定するパラメータです。<br />
例えば以下のように 1d に設定し、2 日後に増分バックアップを取得しようとすると必要なサマリファイルが削除されているため、取得に失敗してしまいます。<br />
そのため、増分バックアップを取得する運用間隔よりも長い期間を設定する必要があります。</p>
<pre># postgresql.conf の wal_summary_keep_time を 1d に設定
wal_summary_keep_time = '1d'

$ ls –l  data/pg_wal/summaries/
-rw-------. 1 postgres postgres 32 11月 1 16:52 0000000100000001CF00002800000001D0000028.summary
# 2 日後に増分バックアップを取得しようとすると失敗
$ date
2025年 11月 3日 月曜日 15:37:55 JST
$ pg_basebackup -D backup/inc_1 --incremental=backup/full/backup_manifest -P -c fast
pg_basebackup: エラー: ベースバックアップを開始できませんでした:
ERROR:  WAL集計がタイムライン1上の1/CD000060から1/CF000028まで必要ですが、そのタイムライン上のそのLSN範囲での集計は不完全です
DETAIL:  この範囲で集計されていない最初のLSNは1/CD000060です</pre>
<h3>フルバックアップ～増分バックアップの保存</h3>
<p>pg_combinebackup をする際に引数フルバックアップ～統合したい世代までのフルバックアップがすべてないと以下エラーとなります。</p>
<pre># 最初の引数にフルバックアップを指定せずに実行
$ pg_combinebackup -o backup/combine_test backup/inc1 backup/inc2
pg_combinebackup: エラー: "backup/inc1"のバックアップは差分バックアップですが、最初のバックアップはフルバックアップである必要があります
# backup/inc_1 を引数に渡さず実行
# LSN 位置に飛びが見られエラーとなる
$ pg_combinebackup -o backup/combine_1 backup/full/ backup/inc_2
pg_combinebackup: エラー: "backup/full/"のバックアップはLSN 1/1A000060で始まっていますが、1/1C000028を期待していました</pre>
<p data-start="68" data-end="234">そのため、実際の運用ではフルバックアップと、最新世代までのすべての増分バックアップを保持しておく必要があります。<br data-start="134" data-end="137" />削除のタイミングとしては、定期的に pg_combinebackup を実行し、統合によって 不要になった過去のフルバックアップおよび増分バックアップを削除するフローになります。</p>
<p data-start="236" data-end="342">また、統合して生成されたバックアップは、次回の pg_combinebackup におけるフルバックアップとして利用可能 であるため、統合元となった古いフルバックアップは削除して問題ありません。</p>
<h3>ストレージ容量</h3>
<p>ストレージコストの低さがメリットの増分バックアップですが、pg_combinebackup をした直後は古いバックアップと統合バックアップが共存する状態になりますので、それらすべてを保存できるストレージサイズを確保する必要があります。</p>
<h1>増分バックアップと<br />
PITR と両立したリストア手順</h1>
<p>増分バックアップ PITR と両立しての増分バックアップを利用することができます。</p>
<p>&nbsp;</p>
<p><img decoding="async" class="alignnone wp-image-19042" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-300x158.png" alt="" width="680" height="358" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-300x158.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-1024x540.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-768x405.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-1536x810.png 1536w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-304x160.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06-282x149.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/12/8986e7ebde3bc9e7dd90e1b7e207af06.png 1859w" sizes="(max-width: 680px) 100vw, 680px" /></p>
<p>PITR(Point In Time Recovery) は WAL アーカイブをもとにして任意の時点までのリストアを可能にするリストア方法です。</p>
<p>WAL アーカイブはデータの変更履歴が記載されたもので、事前に取得しておいたフルバックアップに WAL アーカイブの変更履歴を任意の時点まで適用することで任意の時点に復旧できることが強みのリストア方法です。</p>
<p>この PITR と増分バックアップと両立することで以下メリットが得られます。</p>
<ol>
<li>増分バックアップによるバックアップ取得でストレージコストや取得時間を短く抑えられる</li>
<li>PITR によるリストアでより任意の時点に復旧することができる</li>
</ol>
<p>今回はこれらを両立する設計で具体的な設定手順を紹介します。</p>
<p>まずパラメータの設定を行います。</p>
<pre>#wal をアーカイブする設定
#%p は保管するWALファイルの相対パス, %f がWALのファイル名に置き換わる
archive_mode = on
archive_command = 'cp "%p" "/pg_arc/%f"'
#restore を行う設定
restore_command = 'cp "/pg_arc/%f" "%p"'</pre>
<p>その後増分バックアップ取得を行います。<br />
フルバックアップ、増分バックアップ取得、バックアップの統合、検証の手順で取得します。</p>
<pre># フルバックアップ～バックアップの取得・統合、検証まで実施
$ pg_basebackup  -D backup/full
$ pg_basebackup --incremental=backup/full/backup_manifest -D backup/inc1
$ pg_combinebackup -o backup/combine_full_inc1 backup/full/ backup/inc1
$ pg_verifybackup backup/combine_full_inc1</pre>
<p>その後 mv コマンドで疑似的にデータベースのデータが消えてしまった状態を作ります。</p>
<p>そして統合したバックアップを元のデータディレクトリに mv で移動し、recovery.signal を作成して起動すると PITR のリカバリモードで起動します。<br />
リカバリ終了後に状態を見に行くとデータが指定した時点に復旧していることが分かります。</p>
<pre># データを移動して障害を疑似的に起こす
$ mv data data_crash
# 統合したバックアップを元ディレクトリにコピー
$ cp –r databackup/combine_full_inc1 data
# リカバリモードで起動するよう指示するrecovery.signal を作成して起動
$ touch data/recovery.signal
# 必要に応じて postgresql.conf を設定し復旧タイミングを指定
recovery_target_time = '2025-10-20 14:05:00'
$ pg_ctl start
# ログに以下が出力されていれば復旧完了
LOG: starting archive recovery
LOG: archive recovery complete</pre>
<h1>まとめ</h1>
<p>今回は PostgreSQL 17 で追加された増分バックアップの運用方法と注意点について紹介しました。</p>
<p>PostgreSQL18ではさらに機能が追加されたりと今後より便利になっていく注目の手法です。<br />
紹介した手順を参考に増分バックアップの利用を検討いただけると幸いです。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Pgpool-II 4.6 の紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgpool/pgpool-4-6/</link>
		
		<dc:creator><![CDATA[越野 太基 (Taiki Koshino)]]></dc:creator>
		<pubDate>Mon, 23 Jun 2025 05:00:22 +0000</pubDate>
				<category><![CDATA[Pgpool-II]]></category>
		<category><![CDATA[OSS]]></category>
		<category><![CDATA[Pgpoo-ll 4.6]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=17518</guid>

					<description><![CDATA[2025 年 2 月 28 日、Pgpool-II の新しいメジャーバージョン 4.6 がリリースされました。 Pgpool-II 4.6 では、ロギングコレクター、クエリキャッシュの機能強化がされました。また、バックエ ...]]></description>
										<content:encoded><![CDATA[<p>2025 年 2 月 28 日、Pgpool-II の新しいメジャーバージョン 4.6 がリリースされました。</p>
<p>Pgpool-II 4.6 では、ロギングコレクター、クエリキャッシュの機能強化がされました。また、バックエンドからのメッセージのログ機能の搭載、PostgreSQL 17 への対応、Watchdog の IPv6 への対応も行われました。</p>
<p>Pgpool-II 4.6 の新機能及び変更点は Pgpool-II 公式ドキュメントの以下のページに記載されています。</p>
<p><a href="https://www.pgpool.net/docs/46/ja/html/release-4-6-0.html" target="_blank" rel="noopener">Pgpool-II 4.6 リリースノート</a></p>
<p>本記事では、これらの新機能について詳しく紹介します。</p>
<p><span id="more-17518"></span></p>
<h3>ログのローテーションを指示する新しい PCP コマンド</h3>
<p>Pgpool-II には、PostgreSQL のロギングコレクター(logging_collector) と同様のログ収集機能が備わっています。</p>
<p>ロギングコレクターを使ってログを収集する場合、これまではロギングコレクターにシグナルを送ることでしかログのローテーションを行えませんでしたが、pcp_log_rotate コマンドを使用することで Pgpool-II のログファイルを簡単にローテーションできるようになりました。</p>
<p>動作確認のための設定例は以下の通りです。</p>
<pre><code>(pgpool.conf 設定例)
log_destination = 'stderr' 
logging_collector = on 
log_directory = '/var/log/pgpool_log' 
log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log'</code></pre>
<p><code>log_directory</code> で指定したディレクトリを確認すると、現時点でのログが出力されていることが確認できます。</p>
<pre><code>[root@server1 ~]# ls -l /var/log/pgpool_log/
合計 4
-rw-------. 1 postgres postgres 193 6月 9 16:21 pgpool-2025-06-09_162145.log</code></pre>
<p>その後、 <code>pcp_log_rotate</code> を実行することで新しいログファイルへとローテートされていることが確認できます。</p>
<pre><code>[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</code></pre>
<p>また <code>-s scope</code> オプションによってコマンドの与える影響範囲を指定することができます。サポートされているコマンドスコープは以下です。(デフォルトは <code>local</code>)</p>
<ul>
<li><code>c, cluster</code> : クラスタを構成するすべての Pgpool-II のログファイルをローテーションします。</li>
<li><code>l, local</code> : ローカル Pgpool-II のログファイルをローテーションします。</li>
</ul>
<h3>リロードによる logging_collector 関連のパラメータの変更</h3>
<p><a href="https://www.pgpool.net/docs/46/ja/html/runtime-config-logging.html#GUC-LOGGING-COLLECTOR" target="_blank" rel="noopener">logging_collector</a> 関連の以下の設定パラメータの変更が、Pgpool-II のリロードで反映されるようになりました。これにより <code>logging_collector</code> の設定の反映のために Pgpool-II の再起動の必要がなくなりました。</p>
<ul>
<li><code>log_truncate_on_rotation</code></li>
<li><code>log_directory</code></li>
<li><code>log_filename</code></li>
<li><code>log_rotation_age</code></li>
<li><code>log_rotation_size</code></li>
<li><code>log_file_mode</code></li>
</ul>
<p>リロードで設定が反映されるかの動作確認として <code>log_filename</code> の値を変更したうえで <code>pcp_log_rotate</code> コマンドを実行してログファイルの名前が変更されて出力されるかを確認します。</p>
<p>まず、pgpool.conf を以下の設定に変更し、 Pgpool-II をリロードします。</p>
<pre><code>[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</code></pre>
<p>その後 <code>pcp_rotate_log</code> コマンドを実行すると出力されるログファイルの名前が変更されていることが確認できます。</p>
<pre><code>[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</code></pre>
<h3>クエリキャッシュの強制的な作成</h3>
<p><a href="https://www.pgpool.net/docs/latest/ja/html/runtime-in-memory-query-cache.html" target="_blank" rel="noopener">クエリキャッシュ</a>は <code>SELECT</code> クエリの実行結果を共有メモリに保存し、同じクエリ(パラメータ、データベース、ユーザ含む)が実行されたら、結果を再利用する機能です。PostgreSQL にアクセスせず、ディスクアクセスもないので極めて高速に問い合わせ結果を返すことができます。</p>
<p>Pgpool-II では、クエリキャッシュは通常自動的に作成されますが、安全性の観点から、immutable でない関数を含むクエリ (たとえば <code>SELECT now();</code>) はキャッシュされない仕様になっています。</p>
<p>以下の実行例では、クエリを実行するたびに結果が変化していることがわかります。</p>
<pre><code>postgres=&gt; SELECT now();
now
-------------------------------
2025-06-12 17:10:27.241885+09
(1 行)

postgres=&gt; SELECT now();
now
-------------------------------
2025-06-12 17:10:29.156295+09
(1 行)</code></pre>
<p>また、ログからも毎回 PostgreSQL にアクセスしていることが確認できます。</p>
<pre><code>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();</code></pre>
<p>それでも、内容を理解したうえでキャッシュを行いたいユースケースが存在することから、今回のリリースではクエリキャッシュを強制的に作成する機能が追加されました。クエリの先頭に <code>/*FORCE QUERY CACHE*/</code> を付けて実行することで、クエリキャッシュを強制的に作成できるようになります。</p>
<p>以下のようにクエリを実行することで、キャッシュされた時点のタイムスタンプが返されていることが確認できます。このキャッシュは Pgpool-II を再起動するまで保持されます。</p>
<pre><code>postgres=&gt; /*FORCE QUERY CACHE*/SELECT now();
now
------------------------------
2025-06-12 17:14:47.297804+09
(1 行)

postgres=&gt; /*FORCE QUERY CACHE*/SELECT now();
now
------------------------------
2025-06-12 17:14:47.297804+09
(1 行)</code></pre>
<p>さらに、ログにもキャッシュが利用されていることが記録されています。</p>
<pre><code>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();</code></pre>
<p>また <code>/*NO QUERY CACHE*/</code> を冒頭に付記して宣言しても、 宣言したクエリキャッシュを削除することは出来ません。 <code>/*NO QUERY CACHE*/</code> はキャッシュエントリが作成されないようにするだけなためです。</p>
<p>Pgpool-II を再起動することなく作成したクエリを削除する場合は、後述する <code>PGPOOL SET CACHE DELETE</code> コマンドか、<code>pcp_invalidate_query_cache</code> コマンドを使用する必要があります。</p>
<h3>新しい PGPOOL SET CACHE DELETE コマンド</h3>
<p class="SYNOPSIS">登録されているクエリキャッシュを削除する <a href="https://www.pgpool.net/docs/46/ja/html/sql-pgpool-set-cache.html" target="_blank" rel="noopener"><code>PGPOOL SET CACHE DELETE</code></a> コマンドが追加されました。引数としてクエリの文字列を渡すことによってクエリキャッシュを指定して削除することができます。</p>
<pre><code>postgres=&gt; /*FORCE QUERY CACHE*/SELECT now();
              now
-------------------------------
 2025-06-12 09:58:49.983346+09
(1 行)

postgres=&gt; PGPOOL SET CACHE DELETE '/*FORCE QUERY CACHE*/SELECT now();';
NOTICE:  query cache deleted. query: "/*FORCE QUERY CACHE*/SELECT now();"
SET
postgres=&gt; /*FORCE QUERY CACHE*/SELECT now();
              now
-------------------------------
 2025-06-12 09:59:32.998492+09
(1 行)</code></pre>
<p>引数に記述するクエリキャッシュはクエリ文字列は、末尾の<tt>「;」</tt>も含めて以前のクエリと完全に一致していなければならず、一致しない場合は以下エラーとなります。</p>
<pre><code>postgres=&gt; PGPOOL SET CACHE DELETE '/*FORCE QUERY CACHE*/SELECT now()'; -- 末尾の ';' が不足
NOTICE: query cache does not exist for query: "/*FORCE QUERY CACHE*/SELECT now()" -- クエリキャッシュが存在しないエラーとなる
SET</code></pre>
<h3>クエリキャッシュを削除する新しい PCP コマンド</h3>
<p>すべてのクエリキャッシュを削除する PCP コマンド、<a href="https://www.pgpool.net/docs/46/ja/html/pcp-invalidate-query-cache.html" target="_blank" rel="noopener"><code>pcp_invalidate_query_cache</code></a> が追加されました。</p>
<p>今までは、クエリキャッシュの削除は Pgpool-II の再起動が必要でしたが、このコマンドを実行することによって Pgpool-II を再起動することなくクエリキャッシュを削除することができます。</p>
<p>「<code>/*FORCE QUERY CACHE*/</code>」で 「<code>SELECT now();</code>」 クエリをキャッシュします。</p>
<pre><code>postgres=&gt; /*FORCE QUERY CACHE*/SELECT now();
now
-------------------------------
2025-06-09 13:50:37.066191+09
(1 行)</code></pre>
<p>その後、<tt> </tt><tt class="COMMAND"> <code>pcp_invalidate_query_cache</code> を実行すると、</tt>クエリキャッシュを削除することができます。</p>
<pre><code>[postgres@server1 ~]$ pcp_invalidate_query_cache -h 192.168.100.50 -p 9898 -U pgpool -W
Password:
pcp_invalidate_query_cache -- Command Successful

postgres=&gt; /*FORCE QUERY CACHE*/SELECT now(); -- クエリキャッシュが削除されているため再作成となる
now
-------------------------------
2025-06-09 13:50:56.561619+09
(1 行)</code></pre>
<h3>新しい設定パラメータ log_backend_messages</h3>
<p>バックエンドからのメッセージログを出力する <a href="https://www.pgpool.net/docs/46/ja/html/runtime-config-logging.html#GUC-LOG-BACKEND-MESSAGES" target="_blank" rel="noopener"><code>log_backend_messages</code></a> パラメータが追加されました。<code>terse</code> または <code>verbose</code> に設定されている場合、バックエンドからのメッセージをログ出力します。</p>
<p>以下が受け取るメッセージ例です。</p>
<pre class="PROGRAMLISTING"><code>2025-06-09 14:00:57.494: psql pid 7579: LOG: last ParameterStatus message from backend 0 repeated 13 times</code></pre>
<p><tt class="LITERAL"><code>terse</code> </tt>では、同じ種類のメッセージが同じバックエンドから送られてくると、その回数を記録し、次に異なる種類のメッセージが送られてきた時に繰り返し回数を報告します。そのため、繰り返している最中にセッションに対応するプロセスが強制終了すると、その分のログが出力されません。この場合でもすべてのログを出力するには、 <tt class="LITERAL"><code>verbose</code></tt> オプションを使用します。<br />
<code></code></p>
<p><code>verbose</code> に設定したときのログ出力例は以下です。同一内容のメッセージであっても送られてくるたびに出力するためプロセスの強制終了によるログの損失は避けられますが、大量のメッセージがバックエンドから送られてくる場合は注意が必要です。</p>
<pre><code>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</code></pre>
<h3>PostgreSQL 17 の SQL パーサの導入</h3>
<p>Pgpool-II ではメジャーリリースするたびに、PostgreSQL の最新パーサを移植しています。今回のリリースでは PostgreSQL 17 の新しいパーサを取り込みました。</p>
<p>Pgpool-II の負荷分散機能では、SQL を解析して参照か更新かを判別し、どのノードに振り分けるかを決めています。そのため、PostgreSQL の新バージョンでの SQL の変更に対応するには、SQL パーサを移植する必要があります。</p>
<p>PostgreSQL 17 での SQL のおもな変更点は以下のとおりです。</p>
<ul>
<li><code>MERGE</code> への <code>NOT MATCHED BY SOURCE</code> と <code>RETURNING</code> 句の追加</li>
<li><code>COPY</code> オプションの <code>ON_ERROR ignore</code> と <code>LOG_VERBOSITY</code> の追加</li>
<li><code>COPY FROM</code> オプションの <code>FORCE_NOT_NULLとFORCE_NULL</code> で「*」 を使用した全列を指定できる機能の追加</li>
<li><code>EXPLAIN</code> への <code>SERIALIZE</code> と <code>MEMORY</code> オプションの追加</li>
<li><code>ALTER TABLE</code> で <code>SET STATISTICS DEFAULT</code> を用いて、デフォルトの統計上情報ターゲットとする列の指定できる機能の追加</li>
<li><code>ALTER TABLE</code> での列の生成式を変更する機能の追加</li>
<li><code>ALTER TABLE</code> で <code>.. SET ACCESS METHOD</code> のデフォルトを指定できる機能の追加</li>
<li>イベントトリガでログインイベントと <code>REINDEX</code>  を扱う機能の追加</li>
</ul>
<p>Pgpool-II 4.6 では上記の変更点に対応しています。</p>
<h3>Watchdog の hostname と heartbeat_hostname パラメータの IPv6 対応</h3>
<p>これまで、IPv6 に対応していたパラメータは以下の通りです。</p>
<ul>
<li><code>backend_hostnameX</code></li>
<li><code>listen_addresses</code></li>
<li><code> pcp_listen_addresses</code></li>
</ul>
<p>一方で、以下の Watchdog 関連パラメータはこれまで IPv6 に対応していませんでした。</p>
<ul>
<li><code><code>hostname</code></code></li>
<li><code><code>heartbeat_hostname</code></code></li>
</ul>
<p>今回のリリースにより、<code>hostname</code> と <code>heartbeat_hostname</code> も IPv6 に対応し、すべてのネットワーク関連パラメータで IPv6 アドレスを利用できるようになりました。</p>
<h2>おわりに</h2>
<p>今回は、Pgpool-II 4.6 の新機能について紹介しました。</p>
<p>Pgpool-II 4.6 では、より実用的で便利な機能が数多く追加・改善されています。PostgreSQL の高可用性構成や負荷分散の実現を検討されている方にとって、Pgpool-II は有力な選択肢です。ぜひこの機会に Pgpool-II の導入をご検討ください。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
