<?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>ストリーミングレプリケーション &#8211; SRA OSS Tech Blog</title>
	<atom:link href="https://www.sraoss.co.jp/tech-blog/tag/e187938fc0b4d5e655acf100ec477569/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>Fri, 23 Oct 2026 06:56:23 +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>ストリーミングレプリケーション &#8211; SRA OSS Tech Blog</title>
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>ストリーミングレプリケーションの紹介(2)</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/streaming-replication-2/</link>
		
		<dc:creator><![CDATA[データベース技術グループ]]></dc:creator>
		<pubDate>Fri, 06 Feb 2026 05:25:36 +0000</pubDate>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[ストリーミングレプリケーション]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=19463</guid>

					<description><![CDATA[前回の記事「ストリーミングレプリケーションの紹介(1)」では、PostgreSQL におけるストリーミングレプリケーションの基本機能と構成手順を紹介しました。 ここでは引き続き、ストリーミングレプリケーションの実践的な機 ...]]></description>
										<content:encoded><![CDATA[<p>前回の記事「<a href="https://www.sraoss.co.jp/tech-blog/pgsql/streaming-replication-1/">ストリーミングレプリケーションの紹介(1)</a>」では、PostgreSQL におけるストリーミングレプリケーションの基本機能と構成手順を紹介しました。<br />
ここでは引き続き、ストリーミングレプリケーションの実践的な機能と設定を解説します。</p>
<p>本記事で扱う題目は以下の通りです。</p>
<ul>
<li><a style="color: inherit; text-decoration: underline;" href="#sync_async">同期と非同期</a></li>
<li><a style="color: inherit; text-decoration: underline;" href="#conflict">コンフリクト</a></li>
<li><a style="color: inherit; text-decoration: underline;" href="#stats_view">統計情報ビュー</a></li>
<li><a style="color: inherit; text-decoration: underline;" href="#failover">フェイルオーバー</a></li>
</ul>
<p>記事内の各リンクについて、特記のないものはすべて <a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/index.html" target="_blank" rel="noopener">PostgreSQL16.4 文書</a>（弊社ドメイン）の該当項目へのリンクとなっております。</p>
<p><span id="more-19463"></span></p>
<h2 id="sync_async">同期と非同期</h2>
<h3>同期/非同期の概要</h3>
<p>PostgreSQL のストリーミングレプリケーションには、同期と非同期、2通りのモードがあります。<br />
同期と非同期の違いを簡単に言えば、スタンバイで WAL がどのような状態になったらクライアントにコミット完了を通知するかです。<br />
以下にそれぞれの特徴を示します。</p>
<table>
<thead>
<tr>
<th nowrap="nowrap"></th>
<th><strong>非同期モード</strong></th>
</tr>
<tr>
<td nowrap="nowrap"><strong>通知タイミング</strong></td>
<td>スタンバイで行われる WAL の処理を待たずに、クライアントにコミット完了を通知する</td>
</tr>
<tr>
<td><strong>データの整合性</strong></td>
<td>プライマリでのコミットがスタンバイでの処理を待たないため、プライマリ障害時にデータ損失のリスクがある</td>
</tr>
<tr>
<td><strong>処理性能</strong></td>
<td>レプリケーションを待機する動作が無いため、同期モードに比べて書き込み処理のレスポンスが速い</td>
</tr>
</thead>
</table>
<table>
<thead>
<tr>
<th nowrap="nowrap"></th>
<th><strong>同期モード</strong></th>
</tr>
<tr>
<td nowrap="nowrap"><strong>通知タイミング</strong></td>
<td>synchronous_commit で指定された段階まで、スタンバイ側で WAL 処理が完了したことを待ってから通知する</td>
</tr>
<tr>
<td><strong>データの整合性</strong></td>
<td>プライマリ側でコミット済のトランザクションの内容はプライマリ・スタンバイ両方に書き込まれている</td>
</tr>
<tr>
<td><strong>処理性能</strong></td>
<td>レプリケーション完了まで待機が発生するため、レスポンスが遅くなる可能性がある</td>
</tr>
</thead>
</table>
<p>非同期モードの場合、スタンバイサーバへの複製を待たずにコミット完了するため、プライマリサーバの書き込み性能にほとんど影響を与えないことが特徴です。<br />
しかしながら、プライマリサーバがクラッシュした場合、コミットされた一部のトランザクションがスタンバイサーバに複製されずデータ損失を引き起こす可能性があります。<br />
データ冗長性の実現という観点では、これは大きなリスクとなることに留意してください。</p>
<p>対して同期モードでは、トランザクションのコミットで提供される永続性の保証範囲が拡大されます。<br />
これにより、プライマリサーバのクラッシュ時にも、スタンバイサーバにおいては指定した同期レベルにおいて、データ損失リスクを大きく低減できることが強みとなります。<br />
しかし、コミット完了までに適宜スタンバイでの処理を待つことになるため、プライマリのレスポンスは非同期に比べ遅くなります。</p>
<p>同期と非同期のそれぞれ動作の違いを以下の図に示します。</p>
<p><img fetchpriority="high" decoding="async" class="wp-image-19568 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/32e1b7efef94a3e1b802a30eed6d0fd2-257x300.png" alt="" width="575" height="671" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/32e1b7efef94a3e1b802a30eed6d0fd2-257x300.png 257w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/32e1b7efef94a3e1b802a30eed6d0fd2-184x214.png 184w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/32e1b7efef94a3e1b802a30eed6d0fd2-223x260.png 223w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/32e1b7efef94a3e1b802a30eed6d0fd2.png 632w" sizes="(max-width: 575px) 100vw, 575px" /></p>
<p><img decoding="async" class=" wp-image-19716 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/8b7891476e11249ac53eff0b4cd322ae-280x300.png" alt="" width="625" height="669" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/8b7891476e11249ac53eff0b4cd322ae-280x300.png 280w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/8b7891476e11249ac53eff0b4cd322ae-200x214.png 200w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/8b7891476e11249ac53eff0b4cd322ae-243x260.png 243w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/8b7891476e11249ac53eff0b4cd322ae.png 642w" sizes="(max-width: 625px) 100vw, 625px" /></p>
<p>なお、PostgreSQL のストリーミングレプリケーションは、<strong>デフォルト設定では非同期</strong>となっています。</p>
<h3>同期と非同期の設定パラメータ</h3>
<p>ストリーミングレプリケーションが同期/非同期のどちらのモードで動作するかについては、<br />
主に以下のパラメータによって制御されます。</p>
<ul style="margin: 0; padding-left: 1.2em;">
<li><a style="color: inherit; text-decoration: underline;" href="#synchronous_commit">synchronous_commit</a></li>
</ul>
<p>コミット完了の通知までに、完了しなければならない WAL 処理の段階を指定する</p>
<ul style="margin: 0; padding-left: 1.2em;">
<li><a style="color: inherit; text-decoration: underline;" href="#synchronous_standby_names">synchronous_standby_names</a></li>
</ul>
<p>同期対象として扱うスタンバイサーバを指定する</p>
<p>これらのパラメータはプライマリ側の postgresql.conf で設定します。<br />
ストリーミングレプリケーションがデフォルトで非同期なのは、それぞれのパラメータのデフォルト値が「#synchronous_commit = on」「#synchronous_standby_names = &#8221;（空文字）」であるためです。（詳細は <a style="color: inherit;" href="#synchronous_standby_names_default">synchronous_standby_names</a> の項）</p>
<p>同期モードを指定する場合は、「どのスタンバイを同期対象として扱うか」を synchronous_standby_names で指定し、同期対象スタンバイに対して「どの段階まで WAL 処理の完了を待つか」を synchronous_commit で制御します。</p>
<p>ストリーミングレプリケーションが既に設定されている場合であれば、同期レプリケーションの設定には必要な追加設定は「synchronous_standby_namesを空でない値に設定すること」だけです。<br />
synchronous_commit で同期レベルを off 以外に設定することも必要ですが、前述の通りこれはデフォルト値で on ですので、通常は変更する必要はありません。</p>
<p>詳細については、同期/非同期の基本設定に関する<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/warm-standby.html#SYNCHRONOUS-REPLICATION-CONFIG" target="_blank" rel="noopener">マニュアル</a>をご確認ください。</p>
<h3 id="synchronous_commit">synchronous_commit</h3>
<p>synchronous_commit は、トランザクションのコミットを完了とみなすタイミングを制御するパラメータです。<br />
具体的には、プライマリで行われた更新系トランザクションのコミットがクライアントに「成功」の報告を返す前に、スタンバイ側でどれだけの WAL 処理を完了する必要があるかを決めることで、永続性の保証度合が決まります。</p>
<p>代表的な設定値は以下の通りです。</p>
<table>
<thead>
<tr>
<th><strong>設定値</strong></th>
<th nowrap="nowrap">説明</th>
</tr>
<tr>
<td nowrap="nowrap"><strong>remote_apply</strong></td>
<td>スタンバイ側で WAL が適用（replay）されるまで待つ</td>
</tr>
<tr>
<td><strong>on</strong></td>
<td>スタンバイで WAL がディスクに書き込み（sync）されるまで待つ（デフォルト）</td>
</tr>
<tr>
<td><strong>remote_write</strong></td>
<td>スタンバイで WAL が書き込まれるまで待つ（sync は待たない）</td>
</tr>
<tr>
<td nowrap="nowrap"><strong>local</strong></td>
<td>プライマリでの WAL 書き込みのみ待つ</td>
</tr>
<tr>
<td nowrap="nowrap"><strong>off</strong></td>
<td>WAL の書き込みを待たずにコミット完了とする</td>
</tr>
</thead>
</table>
<p>一般的に、プライマリ障害時におけるコミット済トランザクションの更新欠損を極力回避したい場合は on が選択され、レスポンス性能とのバランスを取りたい場合は remote_write が選択されることが多いです。<br />
remote_apply は、スタンバイ側で WAL が適用（replay）されるまで、プライマリでのコミット通知を待つ設定です。<br />
これにより、スタンバイ側での参照クエリは、プライマリの最新データと整合性を保つことができますが、コミット完了までのレイテンシは on や remote_write と比べて大きくなる点には注意してください。<br />
なお、local や off を指定した場合、synchronous_standby_names を設定していても実質的には非同期動作となります。</p>
<p>それぞれのパラメータにおける動作の違いを以下の図を示します。</p>
<p><img decoding="async" class="wp-image-19828 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/2bd188d0606b56ffa9e145e083276027-300x244.png" alt="" width="736" height="599" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/2bd188d0606b56ffa9e145e083276027-300x244.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/2bd188d0606b56ffa9e145e083276027-768x625.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/2bd188d0606b56ffa9e145e083276027-263x214.png 263w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/2bd188d0606b56ffa9e145e083276027-282x229.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/2bd188d0606b56ffa9e145e083276027.png 937w" sizes="(max-width: 736px) 100vw, 736px" /></p>
<p><img loading="lazy" decoding="async" class="wp-image-19835 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90-300x60.png" alt="" width="760" height="152" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90-300x60.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90-1024x206.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90-768x155.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90-304x61.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90-282x57.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/02/bc39fe0f55fff2d15a87656064a29e90.png 1106w" sizes="auto, (max-width: 760px) 100vw, 760px" /></p>
<p>また、synchronous_commit はいつでも変更可能であるため、SET を用いることで同一サーバ内でもトランザクションごとに同期レベルを使い分けることができます。<br />
例えば、デフォルトが同期コミットの場合でも、特定のトランザクションのみを非同期でコミットしたい場合には、トランザクション内で「SET LOCAL synchronous_commit TO OFF;」を実行することで、そのトランザクションに限り非同期でレプリケーションされます。</p>
<p>パラメータの詳細は<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-wal.html#GUC-SYNCHRONOUS-COMMIT" target="_blank" rel="noopener">マニュアル</a>をご覧ください。</p>
<h3 id="synchronous_standby_names">synchronous_standby_names</h3>
<p>synchronous_standby_names は、同期レプリケーションの対象とするスタンバイサーバ名を指定するパラメータです。<br />
<span id="synchronous_standby_names_default">デフォルトの設定値</span>は空文字「&#8217; &#8216;」となっており、同期対象を指定しない設定になっています。<br />
このように同期対象を指定しなければ、synchronous_commit が off 以外の有効な値であっても、実質的な動作は非同期の挙動となります。</p>
<p>同期対象となるスタンバイサーバを指定する場合は、以下のように設定します。</p>
<pre>synchronous_standby_names = 'standby1'
</pre>
<p>この場合、application_name が standby1 であるスタンバイが同期対象となります。<br />
application_name には、スタンバイ側の postgresql.conf で設定される primary_conninfo において、「application_name = standby1」のように指定された値（サーバ名）が使われます。<br />
この設定は、指定するサーバがスタンバイとして起動している場合（standby.signal が存在する場合）に有効です。</p>
<p>二つ以上の同期スタンバイサーバ名を指定することで、より高いレベルでの高可用性とデータ損失に対する保護が期待できます。<br />
例えば、複数のスタンバイが存在する場合、次のように指定することが可能です。</p>
<pre>synchronous_standby_names = 'ANY 1 (standby1, standby2)'
</pre>
<p>ここで指定した ANY 1 は「standby1 と standby2 のいずれか 1 台が応答すれば同期条件を満たす」という意味になります。<br />
これにより、いずれか一方のスタンバイに障害が発生した場合でも、書き込みが停止する事態を回避できます。</p>
<p>また、ANY 1 ではなく FIRST 1 を指定した場合は、スタンバイ名の記述順がそのまま優先順位となり、リストの先頭にあるスタンバイから順に同期対象として選択されます。</p>
<pre>synchronous_standby_names = 'FIRST 1 (standby1, standby2)'
</pre>
<p>FIRST 1 の場合は、優先スタンバイが応答しない場合でも、wal_sender_timeout により接続は切断され、次に優先度の高いスタンバイが同期対象として選択されます。<br />
そのため FIRST 1 は、「特定のスタンバイを優先しつつ、障害時には自動的に次候補へ切り替えたい」場合に有効な指定方法です。</p>
<p>ANY 1 と FIRST 1の挙動の違いは、以下の図のようになります。</p>
<p><img loading="lazy" decoding="async" class="wp-image-19783 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-298x300.png" alt="" width="641" height="645" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-298x300.png 298w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-150x150.png 150w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-768x774.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-212x214.png 212w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-258x260.png 258w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49-120x120.png 120w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/ab1171a556f421caa45ffe6fee5eaa49.png 776w" sizes="auto, (max-width: 641px) 100vw, 641px" /></p>
<p><img loading="lazy" decoding="async" class="wp-image-19784 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/60b8d9c1269f2f302b16801dcda9983f-300x264.png" alt="" width="688" height="605" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/60b8d9c1269f2f302b16801dcda9983f-300x264.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/60b8d9c1269f2f302b16801dcda9983f-768x676.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/60b8d9c1269f2f302b16801dcda9983f-243x214.png 243w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/60b8d9c1269f2f302b16801dcda9983f-282x248.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2026/01/60b8d9c1269f2f302b16801dcda9983f.png 892w" sizes="auto, (max-width: 688px) 100vw, 688px" /></p>
<p>なお、synchronous_standby_names を単にスタンバイ名をカンマ区切りで列記した場合は、暗黙的に FIRST 1 と同じ振る舞いになります。</p>
<pre>synchronous_standby_names = 'standby1, standby2'</pre>
<p>また、ANY 2 や FIRST 2 のように台数を 1 以上で指定した場合は、指定した台数のスタンバイに対して、synchronous_commit で指定された段階まで WAL の処理が完了するのを待ってから、クライアントにコミット完了が通知されます。</p>
<p>パラメータの詳細は<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES" target="_blank" rel="noopener">マニュアル</a>をご覧ください。</p>
<h3>同期レプリケーション設定時の注意点</h3>
<p>ここまでの説明の通り、同期レプリケーションは同期対象スタンバイからの応答（進捗通知）を必ず待ってから commit を完了するという仕組みになっています。<br />
ですので、指定した同期スタンバイが応答しない場合は commit が完了せず、プライマリでの書き込み処理ができなくなります。</p>
<p>こうした状況を回避するため、同期対象のスタンバイ台数、ネットワーク遅延、スタンバイ側の性能などを考慮し、安定した稼働が実現できる範囲で設計する必要があります。<br />
高可用性を目的とする場合でも、環境での実現性を踏まえたうえで、必ずしも常に同期レプリケーションが最適とは限らない点には注意してください。</p>
<h2 id="conflict">コンフリクト</h2>
<h3>コンフリクトの概要</h3>
<p>コンフリクトは直訳では「衝突」を意味し、PostgreSQL においては主にストリーミングレプリケーション環境において、<strong data-start="1011" data-end="1063">スタンバイサーバ上で発生する、プライマリ側の更新処理とスタンバイ側で実行される参照クエリとの競合</strong>を指します。<br />
PostgreSQL の日本語マニュアルでは、このような競合が起こる状況を「コンフリクト」と表現し、またそうした事象が発生することを「コンフリクトする」と表現しています。<br />
コンフリクトが発生すると、解消のために<strong data-start="530" data-end="582">スタンバイ上で実行中の問い合わせがキャンセルされたり、セッションが終了されたりする場合があります</strong>ので、常に発生する可能性と解消方法を想定して運用することが必要となります。</p>
<p>以下の解説と併せて、マニュアルの該当項目「<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/hot-standby.html#HOT-STANDBY-CONFLICT" target="_blank" rel="noopener">問い合わせコンフリクトの処理</a>」もご覧ください。</p>
<h3>コンフリクトが発生する代表的なケース</h3>
<p>代表的なコンフリクトの例として、以下のようなケースがあります。</p>
<ul>
<li>スタンバイで長時間実行されている参照クエリが存在する</li>
<li>プライマリで VACUUM や DELETE が実行され、不要となった行を削除しようとする</li>
<li>スタンバイ側では、まだ参照中のためその行を削除できない</li>
</ul>
<p>このようなコンフリクトが起きると、スタンバイでは WAL 適用が一時的に妨げられ、<br />
一定時間待機した後、WAL 適用を優先するため、参照クエリがキャンセルされます。</p>
<p>また、コンフリクトは特に<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-replication.html#GUC-HOT-STANDBY" target="_blank" rel="noopener">ホットスタンバイ</a>の設定が「hot_standby = on（デフォルト）」と有効になっている環境で問題となります。</p>
<h3>コンフリクト発生時のエラーメッセージ</h3>
<p>コンフリクトが発生すると、スタンバイ側では以下のようなエラーが出力されます。</p>
<pre>ERROR: canceling statement due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.
</pre>
<p>このエラーは異常動作ではなく、スタンバイでの参照とリカバリ処理の整合性を保つための正常な挙動です。</p>
<h3>コンフリクトへの対処方法</h3>
<p>コンフリクトへの対処方法としては、主に以下の選択肢があります。</p>
<ul>
<li>
<h4>「スタンバイで実行するクエリを短時間で終わるものにする」</h4>
</li>
</ul>
<p>スタンバイで実行される参照クエリの実行時間が短ければ、プライマリ側で生成された WAL を適用する際に競合が発生する可能性は低くなります。<br />
特にスタンバイを参照用途で利用する場合は、長時間トランザクションや大規模な集計処理を避ける設計とすることで、コンフリクトによるクエリキャンセルの発生頻度を抑えることができます。</p>
<ul>
<li>
<h4>「パラメータでスタンバイ側の挙動を調整する」</h4>
</li>
</ul>
<p>代表的なパラメータとして、<a style="color: inherit;" href="#max_standby_streaming_delay">max_standby_streaming_delay</a> や <a style="color: inherit;" href="#hot_standby_feedback">hot_standby_feedback</a> が挙げられます。<br />
これらパラメータを調整することで、コンフリクト発生時のスタンバイの振る舞いを制御できます。</p>
<p>例えば、スタンバイでの参照を優先したい場合は待機時間を長く設定したり、スタンバイ側の参照情報をプライマリに通知することで、クエリキャンセルの発生を抑制することが可能です。</p>
<p>なお重要な注意点ですが、これらのパラメータ調整によってコンフリクトは抑制できても、完全に防ぐことはできません。<br />
状況によっては、スタンバイ側のクエリが ERROR によりキャンセルされるだけでなく、FATAL エラーとして接続自体が切断される場合もあります。</p>
<ul>
<li>
<h4>「コンフリクトによる影響をあらかじめ想定した運用を検討する」</h4>
</li>
</ul>
<p>前述のように、コンフリクトを完全に防ぐことはできないため、スタンバイを参照用途として利用する場合は、コンフリクトでクエリがキャンセルされる可能性を前提とし、エラー発生時にはクエリを再実行できる運用設計も有効です。<br />
特にレポート生成やバッチ処理など、即時性が必須でない参照処理では、スタンバイ上のクエリのキャンセル回避を過度に追求せず、プライマリでの VACUUM が適切に進むことや、更新のスタンバイ反映を速やかに行うことを重視する運用も、現実的な選択肢です。</p>
<p>以下では、これら対処方法のうち、スタンバイ側の挙動を調整するためのパラメータを紹介します。</p>
<h3 id="max_standby_streaming_delay">max_standby_streaming_delay</h3>
<p><a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-replication.html#GUC-MAX-STANDBY-STREAMING-DELAY" target="_blank" rel="noopener">max_standby_streaming_delay</a>：適用されようとしている WAL エントリと競合するスタンバイクエリをキャンセルするまで待機する時間を決定</p>
<p>スタンバイが WAL の適用（リカバリ、replay）をどれだけ遅らせて、競合している参照クエリの終了を待つかを指定するパラメータです。<br />
言い換えるならば、「スタンバイ上の参照クエリがキャンセルされにくいこと」と、「プライマリでの更新をスタンバイに速やかに反映させること」のどちらを優先とするかを決める設定です。</p>
<p>本パラメータの値を大きくすると、スタンバイ側の参照クエリはキャンセルされにくくなります。<br />
ただし、スタンバイでの WAL の適用（リカバリ処理）が遅れるため、プライマリからスタンバイへの反映に時間がかかる場合があります。<br />
一方、値を小さく設定すると遅延（プライマリとのデータ状況の相違）は抑えられるものの、コンフリクト発生時にクエリが早期にキャンセルされやすくなります。</p>
<h3 id="hot_standby_feedback">hot_standby_feedback</h3>
<p><a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-replication.html#GUC-HOT-STANDBY-FEEDBACK" target="_blank" rel="noopener">hot_standby_feedback</a>：ホットスタンバイがスタンバイサーバ上で現在処理を行っている問い合わせについて、プライマリまたは上位サーバにフィードバックを送るか否かを指定</p>
<p>hot_standby_feedback を有効にすると、スタンバイが参照中の行バージョン情報をプライマリに通知することで、コンフリクトの発生を抑制します。<br />
ただしこれに伴い、プライマリ側では VACUUM による不要な行バージョンの回収が遅れる場合があり、不要な行バージョンが残りやすくなることで、テーブルやインデックスの肥大化につながる可能性があります。</p>
<p>ですので、これらの設定は「スタンバイ上の参照クエリがキャンセルされにくいこと」と、「プライマリ側で VACUUM が適切に進み、テーブルの肥大化を抑えること」とのトレードオフとなります。</p>
<h2 id="stats_view">統計情報ビュー</h2>
<h3>レプリケーション状態の確認</h3>
<p>ストリーミングレプリケーションの状態は、PostgreSQL が提供する統計情報ビューを用いて確認できます。<br />
ここでは、運用時に特に重要となるビューを紹介します。</p>
<p>レプリケーションは高可用性や災害対策を目的とする場合がほとんどですので、運用開始以降もこれらのビューを継続的に監視することで、レプリケーションが異常なく動作していることを確認しながら運用することが、レプリケーションの目的を実現するためには必須です。<br />
そういった意味では、単に「切れていないか」だけでなく、遅延が拡大していないか、同期設定が想定通りかといった観点で、定期的に監視することが重要です。</p>
<h3>pg_stat_replication（プライマリ側）</h3>
<p>pg_stat_replication は、プライマリから見たスタンバイの接続状態を確認するためのビューです。<br />
本稿では本ビューのうち、特に有用な列を抜粋いたします。<br />
ビューの全ての列や抜粋した列の詳細を確認する場合は、<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW" target="_blank" rel="noopener">マニュアル該当項</a>を参照してください。</p>
<p>pg_stat_replication ビューの参照は、任意のデータベースにpsqlなどで接続し、以下のような SELECT 文を実行します。</p>
<pre>SELECT pid, application_name, state, sync_state, write_lag, flush_lag, replay_lag
FROM pg_stat_replication;
</pre>
<p>本ビューでは、まずは以下の項目を確認するとよいでしょう。</p>
<table>
<thead>
<tr>
<th><strong>パラメータ</strong></th>
<th nowrap="nowrap">説明</th>
</tr>
<tr>
<td nowrap="nowrap"><strong>pid</strong></td>
<td>WAL 送信プロセスのプロセスID</td>
</tr>
<tr>
<td><strong>application_name</strong></td>
<td>スタンバイ接続時に指定された識別名</td>
</tr>
<tr>
<td><strong>state</strong></td>
<td>WAL送信サーバの現在の状態<br />
streaming であれば、WAL が正常に送信</td>
</tr>
<tr>
<td><strong>sync_state</strong></td>
<td>同期レプリケーションの状態<br />
async（非同期） / sync（同期） / <a style="color: inherit;" href="#quorum"><strong>quorum（詳細は後述）</strong></a>など</td>
</tr>
<tr>
<td><strong>write_lag<br />
flush_lag<br />
replay_lag<br />
</strong></td>
<td>それぞれプライマリとスタンバイ間の遅延状況（単位は秒）</td>
</tr>
</thead>
</table>
<p>これらの項目を監視することで、ストリーミングレプリケーションの状況が正常か確認することができ、なんらかレプリケーションに異常が見られる場合は、<br />
原因を特定するために有用な情報となることも期待できます。</p>
<p>例えば、state が streaming 以外の場合はレプリケーションが正常に行われていない可能性があり、WAL の送信や接続に何らかの問題が発生していることが考えられます。<br />
この場合、スタンバイ側の pg_stat_wal_receiver ビューや PostgreSQL のログと突き合わせて確認することで、原因の切り分けを行うことができます。<br />
他には、*_lag の値が継続的に増加している場合は、性能やネットワークに問題がある可能性があるというふうに見込みをつけるのに役立ちます。<br />
（バックアップ・VACUUM時などの一時的な増加は問題ないと言えます）</p>
<ul>
<li id="quorum">
<h4>補足：sync_state の quorum について</h4>
</li>
</ul>
<p>pg_stat_replication の sync_state 列に quorum と表示される場合、そのスタンバイが「クォーラム方式での同期対象の候補」に含まれている状態を表します。</p>
<p>PostgreSQL のストリーミングレプリケーションにおいては、このクォーラム方式は「synchronous_standby_names に ANY n と指定した際の挙動」と捉えてください。<br />
前述の通り、ANY n を指定した場合、指定した台数（N 台）以上のスタンバイからの進捗通知を待ってから、プライマリはトランザクションの COMMIT を完了します。</p>
<p>このとき、「sync_state = quorum」と表示されたスタンバイは、 「（必要数の応答）n 台を満たすための候補となる集合の一部」 であることを示します。<br />
つまり、quorum は明示的に指定された同期対象ではなく、ANY n 指定時に同期対象となり得るスタンバイ候補の一つであることを示す状態です。</p>
<h3>pg_stat_wal_receiver（スタンバイ側）</h3>
<p>pg_stat_wal_receiver は、スタンバイ側から見た WAL 受信状態を確認するためのビューです。<br />
このビューは、主にスタンバイ側でレプリケーションが停止していないかを確認する際に有用です。</p>
<p>前項と同じく、本稿では本ビューのうち、特に有用な列を抜粋いたします。<br />
ビューの全ての列や抜粋した列の詳細を確認する場合は、<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/monitoring-stats.html#MONITORING-PG-STAT-WAL-RECEIVER-VIEW" target="_blank" rel="noopener">マニュアル該当項</a>を参照してください。</p>
<p>pg_stat_wal_receiver ビューの参照は、任意のデータベースにpsqlなどで接続し、以下のような SELECT 文を実行します。</p>
<pre>SELECT status, receive_start_lsn, received_lsn
FROM pg_stat_wal_receiver;
</pre>
<p>本ビューでは、まずは以下の項目を確認するとよいでしょう。</p>
<table>
<thead>
<tr>
<th><strong>パラメータ</strong></th>
<th nowrap="nowrap">説明</th>
</tr>
<tr>
<td nowrap="nowrap"><strong>status</strong></td>
<td>プライマリからの WAL の受信状態<br />
streaming となっていれば受信し続けている状態</td>
</tr>
<tr>
<td><strong>receive_start_lsn</strong></td>
<td>スタンバイが WAL の受信を開始した位置</td>
</tr>
<tr>
<td><strong>received_lsn</strong></td>
<td>現在までに受信した WAL の最終位置</td>
</tr>
</thead>
</table>
<p>これらの項目を確認することで、スタンバイ側がプライマリから WAL を正しく受信できているかを把握することができます。<br />
特に、status が streaming であり、received_lsn が継続的に進んでいる場合は、WAL の受信に関しては問題が発生していないと判断できます。</p>
<p>一方で、status が streaming であっても received_lsn が長時間変化しない場合は、プライマリ側での WAL 生成が少ない、あるいはネットワークや性能面での問題が発生している可能性が考えられます。<br />
このような場合は、プライマリ側の pg_stat_replication ビューや PostgreSQL のログと突き合わせて確認することで、より詳細な原因の切り分けを行うことができます。</p>
<ul>
<li>
<h4>補足：WAL の LSN の概説</h4>
</li>
</ul>
<p>LSN（Log Sequence Number）とは、平たく言えば WAL の通し番号のようなもので、前述のパラメータにおいては「WAL のどこまで処理が進んでいるかを表す番号」を意味します。</p>
<p>プライマリとスタンバイの関係で考えると、プライマリでは「WAL を生成し、LSN が増えていく」のに対し、スタンバイでは「WAL を受信・適用し、プライマリの LSN を追いかける」という流れになります。</p>
<p>そのため、両者の LSN の差が小さいほど、スタンバイは新しい状態を保っていると言えます。<br />
前述のビューを監視するにあたっては、細かな数値の意味を正確に理解しなくとも、まずは「値が進んでいるか」「止まっていないか」を見るだけでも、レプリケーションの状態把握には役立ちます。</p>
<h2 id="failover">フェイルオーバー</h2>
<h3>PostgreSQL本体でできること・できないこと</h3>
<p>ストリーミングレプリケーションは高可用性構成の基盤となる技術ですが、PostgreSQL 本体には以下の機能は含まれていません。</p>
<ul>
<li>障害検知</li>
<li>自動フェイルオーバー</li>
<li>スプリットブレイン防止</li>
</ul>
<p>そのため、フェイルオーバーの設計と運用は、外部ツールを利用したり、独自にスクリプトを組むなどの対応が必要となります。<br />
本記事では、フェイルオーバーに関わる概要を説明します。</p>
<p>外部ツール利用やスクリプト構築についての詳細は、続編記事にて紹介予定のため、ここでは割愛いたします。</p>
<h3>手動フェイルオーバーの基本</h3>
<p>前回の記事でも紹介した通り、スタンバイは pg_ctl promote などの手段でプライマリへ昇格できます。</p>
<pre>pg_ctl promote -D データディレクトリのパス</pre>
<p>昇格後は、該当スタンバイは新しいプライマリとして更新を受け付けるようになります。</p>
<h3>フェイルオーバー時の注意点</h3>
<p>フェイルオーバー時に特に注意すべき点は以下の通りです。</p>
<ul>
<li>旧プライマリが完全に停止していることを確認する</li>
<li>同時に複数のプライマリが存在しないようにする</li>
<li>アプリケーションの接続先を確実に切り替える</li>
</ul>
<p>これらが守られない場合、フェイルオーバー処理自体は正しく完了しても、スプリットブレイン（データ不整合）が発生する危険性があります。<br />
※スプリットブレイン：複数のノードが同時にプライマリとして動作し、互いに異なる更新を受け付けてしまう状態</p>
<p>なお、同期レプリケーション構成であってもすべてのスタンバイが、常にプライマリの最新データと整合した状態になるとは限りません。<br />
synchronous_standby_names の設定（ANY / FIRST）やスタンバイの接続状態によっては、同期条件を満たしていないスタンバイが存在する可能性があります。<br />
そのため、フェイルオーバー時には「どのスタンバイが実際に同期対象であったか」、およびそのスタンバイが「昇格対象が最新の WAL を反映しているか」を必ず確認するようにしてください。</p>
<h3>障害検知</h3>
<p>障害検知として一般的な方法としては、定期的な ping による疎通確認や、PostgreSQL の待ち受けポートへの接続確認、もしくは pg_isready を用いたプロセスの死活監視などが考えられます。</p>
<p>例えば、そもそもサーバ自体に到達できない場合は OS やネットワーク障害が疑われます。<br />
もしくはポートには接続できても pg_isready が失敗する場合は、PostgreSQL のプロセス停止や応答不能が疑われるといったように、障害を切り分けることができます。</p>
<p>このように、複数の観点から段階的に監視を行うことで、単純な通信断とデータベース障害とを区別しやすくなり、フェイルオーバーの判断を誤るリスクを低減できます。</p>
<h3>自動フェイルオーバーを行う場合</h3>
<p>自動フェイルオーバーを実現したい場合は、以下のような外部ツールとの組み合わせが一般的です。</p>
<ul>
<li>Pacemaker + Corosync</li>
<li>pgpool-II</li>
</ul>
<p>これらに関しての導入・操作手順は今回割愛し、次回以降の続編でご紹介する予定です。</p>
<p>自動フェイルオーバーを導入する場合、いずれもストリーミングレプリケーション単体の挙動を理解していることが前提となります。<br />
まずは手動でのフェイルオーバー手順を確実に把握し、その後に自動化を検討するのが安全です。</p>
<h2>最後に</h2>
<p>本記事では、ストリーミングレプリケーションにおける同期設定、コンフリクト、監視、フェイルオーバーといった運用面で重要となるポイントを紹介しました。<br />
ストリーミングレプリケーションは強力な機能ですが、その特性を正しく理解し、用途に応じた設計・運用を行うことが不可欠です。</p>
<p>次回以降では、pgpool-II や Pacemaker + Corosync を利用した自動フェイルオーバーの構築についての情報をお伝えする予定です。</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>

<div>
<div style="background-color: #fffacd; padding: 20px; border-radius: 8px; text-align: center;">2026/10/27（火）「PostgreSQL 19 リリース記念セミナー」開催！<br />
コントリビューターが新機能をわかりやすく解説します。<br />
詳しくは<a href="https://www.sraoss.co.jp/event_seminar/detail/20261027-postgresql19-webinar/?utm_source=techblog&amp;utm_medium=email&amp;utm_campaign=pg19-seminar" target="_blank" rel="noopener"><strong style="color: #2581c4;">こちら</strong></a>をご覧ください。</div>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ストリーミングレプリケーションの紹介(1)</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/streaming-replication-1/</link>
		
		<dc:creator><![CDATA[データベース技術グループ]]></dc:creator>
		<pubDate>Fri, 09 May 2025 00:00:09 +0000</pubDate>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[ストリーミングレプリケーション]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=17368</guid>

					<description><![CDATA[本記事では、PostgreSQL 9.0 より導入された「ストリーミングレプリケーション」の概要、構築方法について紹介します。 記事内の各リンクについて、特記のないものはすべてPostgreSQL16.0文書の該当項目へ ...]]></description>
										<content:encoded><![CDATA[<p>本記事では、PostgreSQL 9.0 より導入された「ストリーミングレプリケーション」の概要、構築方法について紹介します。</p>
<p>記事内の各リンクについて、特記のないものはすべて<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/index.html" target="_blank" rel="noopener noreferrer">PostgreSQL16.0文書</a>の該当項目へのリンクとなっております。</p>
<p><span id="more-17368"></span></p>
<h2><strong>ストリーミングレプリケーションの概要</strong></h2>
<h3>ストリーミングレプリケーションとは</h3>
<p>ストリーミングレプリケーションとは、PostgreSQL 9.0以降で利用できる本体組み込みのレプリケーション機能です。</p>
<p>本機能はWAL（Write Ahead Logging）をベースに実現しています。<br />
具体的には、プライマリが送信したWALをスタンバイ側が受信し、スタンバイ側でそのWALをリプレイすることによりプライマリと同じ状態を保つ（リカバリし続ける）、という仕組みになっています。</p>
<p><a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/warm-standby.html#STREAMING-REPLICATION" target="_blank" rel="noopener noreferrer">PostgreSQL16.0文書 パートIII.サーバの管理 27.2.5 ストリーミングレプリケーション</a></p>
<h3>プライマリとスタンバイ</h3>
<p>プライマリやスタンバイといったサーバに対する呼び方を整理します。<br />
ストリーミングレプリケーションを構成するサーバは、以下のふたつの役割に分けられます。</p>
<table>
<thead>
<tr>
<td><strong>プライマリ</strong>（Primary）</td>
<td>クライアントから直接データ更新を受けつけるサーバ</td>
</tr>
<tr>
<td><strong>スタンバイ</strong>（Standby）</td>
<td>プライマリ側のデータ変更を追跡するサーバ</td>
</tr>
</thead>
</table>
<p>これらの関係は柔軟であり、プライマリから複数のスタンバイを並列で繋ぐ構成や、スタンバイをさらに別のスタンバイに接続する構成などを組み合わせることも可能です。<br />
本記事では前者をマルチスタンバイ構成、後者をカスケード構成と呼ぶことにし、以下の図に表します。<img loading="lazy" decoding="async" class="wp-image-17403 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489-300x202.png" alt="" width="620" height="418" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489-300x202.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489-1024x691.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489-768x518.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489-304x205.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489-282x190.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/7df6010ed2b480fbe81b1a7013669489.png 1128w" sizes="auto, (max-width: 620px) 100vw, 620px" /></p>
<h3>ストリーミングレプリケーション導入の背景</h3>
<p>PostgreSQL 9.0でストリーミングレプリケーションが実装されるまで、PostgreSQLでのレプリケーションには外部ツールを用いてきました。<br />
この外部ツールの多くは「プライマリに実行されたものと同様のSQLをスタンバイに転送し実行する」ことでレプリケーションを実現しているものでした。<br />
当時のPostgreSQLコア開発コミュニティでは用途に合わせて様々なレプリケーションツールが開発されていましたが、それらのプロダクトもいつまで使えるかの保証はなく、デファクトスタンダードとなるツールが必要とされる状況にありました。<br />
こうした背景から、ストリーミングレプリケーションはPostgreSQLにおけるレプリケーションのデファクトスタンダードを目指して開発されました。</p>
<p>前述のようにストリーミングレプリケーションはWALベースの仕組みであり、その点においてそれまでのSQLベースの外部ツールとは異なります。<br />
SQLベースでは、複雑なクエリの処理によりレプリケーションの遅延が発生したり、SQL文が意図しない結果を引き起こしデータ整合性のリスクが生じる場合があります。<br />
こうした点において、WALベースのストリーミングレプリケーションでは、SQLベースのレプリケーションと比べ一般的に下記のようなメリットがあります。</p>
<table>
<thead>
<tr>
<td nowrap="nowrap"><strong>データ整合性の確保</strong></td>
<td>物理レベルのデータを転送するため、データベースの完全なコピーとなる</td>
</tr>
<tr>
<td><strong>処理の低遅延性</strong></td>
<td>SQLステートメントを実行しないため、レプリケーションの遅延が少ない場面が多い</td>
</tr>
</thead>
</table>
<p>ただし、ストリーミングレプリケーションでは物理レベルでのデータ転送が行われるため、ストレージやネットワーク帯域幅の消費が増加する可能性があります。<br />
プライマリ・スタンバイ間のネットワーク帯域が不足している場合だと、データ転送量によっては遅延が発生することを考慮した方がよいでしょう。</p>
<p>それでも、データの整合性を重視する場面では、ストリーミングレプリケーションは優れた選択肢といえます。</p>
<h3>ストリーミングレプリケーションでできること</h3>
<p>ストリーミングレプリケーションによって、実現できる用途の代表は以下の通りです。</p>
<table>
<thead>
<tr>
<td><strong>高可用性</strong>（HA）</td>
<td>システム障害に備えた冗長化</td>
</tr>
<tr>
<td><strong>災害対策</strong>（DR）</td>
<td>遠隔地のスタンバイでデータの安全性確保</td>
</tr>
<tr>
<td><strong>負荷分散</strong></td>
<td>読み取り専用ノードを用いてクエリ負荷を分散</td>
</tr>
</thead>
</table>
<p>注意点として、障害検知機能やそれに伴う自動フェイルオーバー機能、及び負荷分散の自動化機能は<strong>PostgreSQL本体は提供していません</strong>。<br />
これらの機能を求める場合は、外部のHAソフトウェアやクラスタリングソフトウェアなどと組み合わせるなどの対応が必要となります。<br />
また、プライマリのデータをコピーするという点では、バックアップと役割が似ているようにも見えますが、レプリケーションの場合は誤操作なども含めレプリケーションされてしまうため、一般に<strong>バックアップにはなりません</strong>。</p>
<h3>同期/非同期の違いについて</h3>
<p>同期と非同期の違いは、スタンバイでWALがどのような状態になったらクライアントにコミット完了を通知するかです。<br />
以下にそれぞれの特徴を示します。</p>
<table>
<thead>
<tr>
<th nowrap="nowrap"></th>
<th><strong>同期モード</strong></th>
</tr>
<tr>
<td nowrap="nowrap"><strong>通知タイミング</strong></td>
<td>スタンバイでWALが正常に書き込みされたことを待ってから、クライアントにコミット完了を通知する</td>
</tr>
<tr>
<td><strong>データの整合性</strong></td>
<td>プライマリ側でコミット済のトランザクションの内容はプライマリ・スタンバイ両方に書き込まれる</td>
</tr>
<tr>
<td><strong>処理性能</strong></td>
<td>レプリケーション完了まで処理が続くため、パフォーマンスが悪化する可能性がある</td>
</tr>
</thead>
</table>
<table>
<thead>
<tr>
<th nowrap="nowrap"></th>
<th><strong>非同期モード</strong></th>
</tr>
<tr>
<td nowrap="nowrap"><strong>通知タイミング</strong></td>
<td>スタンバイで行われるWALに対する処理を待たずに、クライアントにコミット完了を通知する</td>
</tr>
<tr>
<td><strong>データの整合性</strong></td>
<td>プライマリでのコミットがスタンバイでのコミットを待たないため、プライマリの故障時にデータ損失のリスクが高まる</td>
</tr>
<tr>
<td><strong>処理性能</strong></td>
<td>高速で効率的な動作が可能で、遅延が少ないため同期に比べてパフォーマンスの向上が見込まれる</td>
</tr>
</thead>
</table>
<p>ここでは詳細は割愛しますが、同期/非同期はプライマリの<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-wal.html#SYNCHRONOUS-COMMIT-MATRIX" target="_blank" rel="noopener noreferrer">synchronous_commitパラメータ</a>などで設定します（デフォルトは非同期設定）。</p>
<h3>ロジカルレプリケーションとストリーミングレプリケーションの違いについて</h3>
<p>ストリーミングレプリケーションの特徴は、データベースクラスタ全体が物理レベルでレプリケーションされることで、プライマリとスタンバイのデータを同じ状態に保てることです。<br />
あくまでデータベースクラスタ全体でのレプリケーションであるため、特定のテーブルや列のみを対象として限定することはできません。<br />
また、構造が異なる環境どうしではレプリケーションできず、<strong>異なるメジャーバージョン間やOS間では利用できません</strong>。</p>
<p>対してロジカルレプリケーションでは、データベースやテーブル単位でWALの変更情報を論理的なレベルに変換（デコード）して転送します。<br />
こちらは論理的な変更を行うため、<strong>異なるメジャーバージョン間やOS間でもレプリケーション可能</strong>です。<br />
また、<strong>特定のテーブルや列のみを対象にしたレプリケーションも可能</strong>となっております。</p>
<p>これらの特徴を踏まえ、用途によってどちらのレプリケーションを利用するかを選ぶことで、より効率的なデータベースの運用ができるでしょう。</p>
<table>
<thead>
<tr>
<td nowrap="nowrap"><strong>ストリーミングレプリケーション</strong></td>
<td>高可用性構成や参照負荷の分散に適している</td>
</tr>
<tr>
<td><strong>ロジカルレプリケーション</strong></td>
<td>データ移行や特定データの統合・集約に適している</td>
</tr>
</thead>
</table>
<p>ロジカルレプリケーションの詳細については、以下の記事をご覧ください。</p>
<p>SRA OSS Tech Blog： <a href="https://www.sraoss.co.jp/tech-blog/pgsql/logical-replication-1/" target="_blank" rel="noopener noreferrer">ロジカルレプリケーションの紹介（１）</a></p>
<h2>ストリーミングレプリケーションの構築</h2>
<p>実際にストリーミングレプリケーションが動作する環境を構築していきます。<br />
ここではプライマリに対してスタンバイは一台、非同期モードでストリーミングレプリケーションを構成します。<br />
今回ご紹介する検証環境は以下の通りです。</p>
<table>
<thead>
<tr>
<td nowrap="nowrap">ホストOS</td>
<td>Rocky Linux 9.5</td>
</tr>
<tr>
<td>DBMS</td>
<td>PostgreSQL 16.8（<a href="https://yum.postgresql.org/repopackages/" target="_blank" rel="noopener noreferrer">PGDGのリポジトリRPM</a>からインストール）<br />
スーパーユーザー（管理ユーザ）は「postgres」</td>
</tr>
</thead>
</table>
<p>※PGDG：<a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">PostgreSQL Global Development Group</a></p>
<p><img loading="lazy" decoding="async" class="wp-image-17490 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/4ba5d664ce36afe80cd6f0c91a15ccdb-300x202.png" alt="" width="734" height="494" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/4ba5d664ce36afe80cd6f0c91a15ccdb-300x202.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/4ba5d664ce36afe80cd6f0c91a15ccdb-768x517.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/4ba5d664ce36afe80cd6f0c91a15ccdb-304x205.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/4ba5d664ce36afe80cd6f0c91a15ccdb-282x190.png 282w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2025/04/4ba5d664ce36afe80cd6f0c91a15ccdb.png 842w" sizes="auto, (max-width: 734px) 100vw, 734px" /></p>
<h3>①プライマリの準備</h3>
<p>ストリーミングレプリケーション構築の準備として、プライマリ側の設定を行います。<br />
まずはプライマリのデータベースクラスタを作成します。<br />
以降の説明では、/usr/pgsql-16/bin/ に PATH を通してある前提で話を進めます。</p>
<pre>$ initdb 
$ ls /var/lib/pgsql/16/data</pre>
<h4>・postgresql.confの設定（プライマリ）</h4>
<p>下記のパラメータはどちらもデフォルト値となっています。</p>
<pre>$ cat /var/lib/pgsql/16/data/postgresql.conf
#wal_level = replica
#max_wal_senders = 10
</pre>
<p>ここでは<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-wal.html#GUC-WAL-LEVEL" target="_blank" rel="noopener noreferrer">wal_level</a>にreplicaを指定していますが、logicalを指定しても動作には問題ありません。<br />
replicaに設定することで、WALアーカイビングおよびレプリケーションをサポートするために十分なデータを書き出します。<br />
<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-replication.html#GUC-MAX-WAL-SENDERS" target="_blank" rel="noopener noreferrer">max_wal_senders</a>はWALを送信するプロセスの最大数を設定します。<br />
スタンバイを複数台接続する場合は、適宜この値も調整するようにしてください。</p>
<h4>・pg_hba.confの設定</h4>
<p>後述するpg_basebackupの実行クライアントやスタンバイは、プライマリに対してレプリケーション接続を行います。<br />
下記の通り、クライアント認証はデフォルトで仮想的なデータベース名replicationを指定し設定されています。</p>
<pre>$ cat /var/lib/pgsql/16/data/pg_hba.conf
# Allow replication connections from localhost, by a user
# with the replication privilege.
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust</pre>
<p>ここでは検証のために認証をtrustに設定していますが、レプリケーション接続ができるとデータの変更内容を受信できるため、現実的ではありません。<br />
実際には<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/auth-password.html" target="_blank" rel="noopener noreferrer">SCRAM-SHA-256</a>を指定するなど、<strong>セキュリティを考慮した設定にしてください</strong>。</p>
<h3>②スタンバイの準備</h3>
<p>プライマリのデータベースクラスタをコピーし、スタンバイとして接続できるようにします。</p>
<h4>・プライマリを起動する</h4>
<pre>$ pg_ctl start -D /var/lib/pgsql/16/data</pre>
<h4>・プライマリからベースバックアップを取得する</h4>
<pre>$ pg_basebackup -p 5432 -D /var/lib/pgsql/16/data2 -R -P
24549/24529 kB (100%), 1/1 tablespace</pre>
<p>-Rオプションを指定すると、レプリケーションに必要な最低限の設定がpostgresql.auto.confに追加され、standby.signalが生成されます。</p>
<h4>・postgresql.confの設定（スタンバイ）</h4>
<pre>$ vi /var/lib/pgsql/16/data2/postgresql.conf
#hot_standby = on
port = 5433</pre>
<p>hot_standbyはリカバリ中のスタンバイが接続を受けつけ、参照ができるかを指定するパラメータです。（デフォルトでon）<br />
portは通常変更する必要はありません。<br />
ここでは同じホスト上でスタンバイを起動するため、プライマリのportと重複しないように変更しています。</p>
<h4>・postgresql.auto.confの確認</h4>
<p>編集は行わず、関連箇所のみ確認します。<br />
前述のようにpg_basebackupで-Rオプションを指定して実行すると、接続先のプライマリの情報をもとにスタンバイの設定が自動的に追加されます。</p>
<pre>$ cat /var/lib/pgsql/16/data2/postgresql.auto.conf
primary_conninfo = 'user=postgres passfile=' '/var/lib/pgsql/.pgpass' '(以下略)'
</pre>
<p><a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/runtime-config-replication.html#RUNTIME-CONFIG-REPLICATION-STANDBY" target="_blank" rel="noopener noreferrer">primary_conninfo</a>は接続先のプライマリの接続文字列を指定するパラメータです。</p>
<h4>・standby.signalの確認</h4>
<p><a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/warm-standby.html#STANDBY-SERVER-OPERATION" target="_blank" rel="noopener noreferrer">standby.signal</a>はスタンバイとして起動するかを指定する<strong>空のファイル</strong>です。<br />
データベースクラスタ内にこのファイルが存在すると、サーバはスタンバイモードで起動されます。<br />
ここではpostgresql.auto.confと同様に、pg_basebackupで-Rオプションを指定して実行したことで、<strong>自動的に生成</strong>されています。</p>
<pre>$ ls /var/lib/pgsql/16/data2/standby.signal</pre>
<h3>③レプリケーションの動作確認</h3>
<p>これでストリーミングレプリケーションの準備は整いました。<br />
ここからは以下の検証を行い、レプリケーションの動作を確認します。</p>
<ul>
<li>プライマリに挿入したデータが、スタンバイにコピーされているか</li>
<li>スタンバイでデータの挿入や削除が行えないようになっているか</li>
</ul>
<p>それでは検証を実施していきましょう。</p>
<p>まずはスタンバイを起動します。</p>
<pre>$ pg_ctl start -D /var/lib/pgsql/16/data2</pre>
<p>次にプライマリに検証用のデータベース及びテーブルを作成し、データを挿入します。</p>
<pre>$ createdb -p 5432 repdb
$ psql -p 5432 repdb
=# CREATE TABLE t (c int);
=# INSERT INTO t VALUES (1);
=# SELECT * FROM t;
 c 
---
 1
(1 row)
</pre>
<p>スタンバイに上記のデータが同期されているか、参照で確認します。</p>
<pre>$ psql -p 5433 repdb
=# SELECT * FROM t;
 c 
---
 1
(1 row)</pre>
<p>プライマリで挿入したデータがスタンバイでも参照できました。<br />
次にスタンバイのデータに挿入を行えるかを検証してみます。</p>
<pre>=# INSERT INTO t VALUES (2);
ERROR: cannot execute INSERT in a read-only transaction</pre>
<p>このようにスタンバイに挿入を試みてもエラーになります。<br />
ストリーミングレプリケーションの基本的な動作を確認することができました。</p>
<p>また、レプリケーションの確認として、<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW" target="_blank" rel="noopener noreferrer">pg_stat_replicationビュー</a>にエントリが存在するも確かめてみましょう。</p>
<pre>$ psql -p 5432
=# SELECT * FROM pg_stat_replication;

-[ RECORD 1 ]----+------------------------------
～省略～
state      | streaming
sync_state | async</pre>
<p>上記の state が streaming であることから、レプリケーションが正常に動作していると判断できます。<br />
また、sync_state が async（非同期）であることも確認できます。</p>
<h2>スタンバイ昇格と復旧手順</h2>
<p>「プライマリが何らかの不具合で停止してしまった」<br />
そんな時のために、ここではスタンバイをプライマリに昇格する手順をご紹介します。</p>
<h3>①スタンバイの昇格手順</h3>
<p>スタンバイをプライマリに昇格させる方法は複数あります。</p>
<ul>
<li>コマンドラインでpg_ctl promote用いる方法</li>
<li>SQLでpg_promote関数を実行する方法</li>
<li>promote_trigger_fileを用いる方法（PostgreSQL 15以前）</li>
</ul>
<p>ここでは代表例として、コマンドラインで<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/app-pg-ctl.html" target="_blank" rel="noopener noreferrer">pg_ctl promote</a>を実行する方法を紹介します。</p>
<pre>$ pg_ctl promote -D /var/lib/pgsql/16/data2
waiting for server to promote.... done
server promoted</pre>
<p>これでスタンバイが新プライマリに昇格しました。<br />
新プライマリが更新を受けつけることを確認します。</p>
<pre>$ psql -p 5433 repdb
=# INSERT INTO t VALUES (3);
=# SELECT * FROM t;
 c 
---
 1
 3
(2 rows)</pre>
<p>新プライマリでデータの更新ができました。<br />
一応データベースクラスタ内のstandby.signalの有無も確認してみましょう。</p>
<pre>$ ls /var/lib/pgsql/16/data2/standby.signal</pre>
<p>スタンバイではなくなったことで、当該ファイルは除去されています。<br />
なお、promote後は旧プライマリとのレプリケーションはなくなり、改めて<strong>新プライマリのシングル構成</strong>となっています。</p>
<h3>②旧プライマリを新スタンバイにする手順と注意点</h3>
<p>新スタンバイが昇格後、旧プライマリ側で一切WAL書き込みが発生していない状況なら、旧プライマリを新スタンバイとして組み込み可能です。<br />
ですので、旧プライマリと旧スタンバイを単純に入れ替える場合ならば、<strong>旧プライマリを停止したうえで旧スタンバイを新プライマリに昇格する</strong>のが確実です。</p>
<p>しかし旧プライマリと新プライマリの間にデータのずれがある状況では、単純に旧プライマリを新スタンバイとしてレプリケーションを構築することができません。<br />
その場合、以下の方法でスタンバイを構築する必要があります。</p>
<ul>
<li>再度新プライマリから pg_basebackup で ベースバックアップを取得しなおす</li>
<li>pg_rewindで旧プライマリを新プライマリと同期させる</li>
</ul>
<h4>・pg_basebackupを用いる場合</h4>
<p>一つ目の方法のベースバックアップに関しては、前述の「ストリーミングレプリケーションの構築」で紹介したと同様の手順で実行できます。<br />
基本的にはこちらの方法で愚直にバックアップを取り直したうえで、改めてレプリケーションを構成することが安全で確実といえます。</p>
<h4>・pg_rewindを用いる場合</h4>
<p>二つ目の方法の<a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/app-pgrewind.html" target="_blank" rel="noopener noreferrer">pg_rewind</a>を使用するには以下の条件をクリアしている必要があります。</p>
<ul>
<li>事前にwal_log_hintsをonに設定しておく。（デフォルトはoff）<br />
もしくは<span class="application"><a href="https://www.sraoss.co.jp/PostgreSQL/Manual/document/16/app-pgchecksums.html" target="_blank" rel="noopener noreferrer">pg_checksums</a> -eで</span>データチェックサムを有効にしておく。（-e オプションで有効化）</li>
<li>full_page_writesをonにしておく。（デフォルトでon）</li>
</ul>
<p>これらの設定は後から設定しても、その直後はpg_rewindを使用できないため、あらかじめ設定しておくことを忘れないようにしてください。<br />
データベースクラスタが大きい場合には、pg_rewindの方がベースバックアップに比べて復旧時間が短縮できます。<br />
これはpg_rewindの方が差分同期で済むためです。</p>
<p>pg_rewindとpg_basebackupのどちらの手段を選択するかは、ストリーミングレプリケーションを構成する際にあらかじめ想定しておくとよいでしょう。</p>
<h2>最後に</h2>
<p>本記事ではストリーミングレプリケーションの概要と、基本的な構築手順をご紹介いたしました。<br />
次回以降では、</p>
<p>・同期と非同期についての詳細<br />
・コンフリクトについて<br />
・統計情報ビューの確認方法<br />
・フェイルオーバーについて</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>

<div>
<div style="background-color: #fffacd; padding: 20px; border-radius: 8px; text-align: center;">2026/10/27（火）「PostgreSQL 19 リリース記念セミナー」開催！<br />
コントリビューターが新機能をわかりやすく解説します。<br />
詳しくは<a href="https://www.sraoss.co.jp/event_seminar/detail/20261027-postgresql19-webinar/?utm_source=techblog&amp;utm_medium=email&amp;utm_campaign=pg19-seminar" target="_blank" rel="noopener"><strong style="color: #2581c4;">こちら</strong></a>をご覧ください。</div>
</div>

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