将来のPostgreSQL：レプリケーション・プロトコルの改良

<font color="Grey">*[Future PostgreSQL: Improvement to the Replication Protocol](https://aiven.io/blog/future-postgresql-improvement-to-the-replication-protocol)の翻訳です。*</font>

2022年1月13日

# 将来のPostgreSQL：レプリケーション・プロトコルの改良

OSPOチームが信頼性問題の解決に貢献したPostgreSQLレプリケーションの最新の改良をご覧ください。

今日の投稿はPostgreSQLの新機能（PostgreSQL 15で実装予定）についてです。

で時々遭遇する信頼性の問題を解決するためにAivenが開発したものです。

を解決するためにAivenが開発した新しい機能（PostgreSQL 15に実装予定）についてです。READ_REPLICATION_SLOT`コマンドは物理的なレプリケーションを、PostgreSQL 15で使用されるようにします。

クライアント、特に `pg_receivewal` の信頼性を向上させます。


AivenのOSPOオフィスでは、Aivenのオープンソース製品に時間を割いています。

が提供または開発するオープンソース製品に時間を割いており、この機能で協力できたことを非常に嬉しく思っています。


## PostgreSQL レプリケーションの驚き


この物語は、私たち自身の[PgHoard](https://github.com/aiven/pghoard)から始まります。

[PITR](https://www.postgresql.org/docs/current/continuous-archiving.html)

バックアップツールから始まります。PgHoardはWALをアーカイブするためにいくつかの方法を提供します。

(Write Ahead Log)をアーカイブする方法があります。

[pg_receivewal`](https://www.postgresql.org/docs/current/app-pgreceivewal.html)、

に接続するPostgreSQLで出荷されている小さなアプリケーションです。

クラスタに物理的なレプリケーションプロトコルを使用して接続し、WALをストリーミングします。

を使用してサーバ上の位置を追跡することもできます。

レプリケーションスロット


PgHoardが再起動された時に、WALが失われることがあることに気づきました。

を再起動すると、WAL が失われることがあることに気づきました。これは、`pg_receivewal`がWALの開始を決定するためです。

の開始位置をこのように決めるからである：


* アーカイブフォルダにどのようなセグメントがあるかを調べ、そのセグメントから再開する。

アーカイブフォルダにどのセグメントがあるかを調べ、最新のアーカイブから再開する。
* アーカイブ・フォルダーが空の場合は、現在のサーバーのLSNの位置から開始する。


問題は、私たちの場合、`pg_receivewal`が別のサーバーで起動されたので、そのサーバーのLSNの位置から開始しなければならないことである。

から再開したことです。

現在の LSN (Log Sequence Number) の位置から再開したことです。


pg_receivewal`を起動し、次のコマンドの後に停止させることで、この動作を観察することができる。

を起動し、いくつかのWALがアーカイブされた後に停止させ、そのディレクトリを空にして再度起動させることで、この動作を観察することができます：



```
sudo -u postgres pg_receivewal -D /tmp/wals -v -s pg_receivewal\_slot
pg_receivewal: 47/E5000000でログストリーミングを開始します (タイムライン1)
pg_receivewal: 47/E600000000でセグメントを終了しました（タイムライン1）。
pg_receivewal: 割り込みシグナルを受信しました。
pg_receivewal: "00000001000047000000E6.partial "の名前を変更していません。
pg_receivewal: 割り込みシグナルを受け取りました。
❯ sudo rm /tmp/wals/* -rf
# サーバ上でWALが生成されるのを待ち、pg_receivewalを再起動します。
❯ sudo -u postgres pg_receivewal -D /tmp/wals -v -s pg_receivewal_slot
pg_receivewal: log streaming at 47/E9000000 (timeline 1)`Copy to clipboard
```

ここで、セグメント `00000001000047000000E7` と

00000001000047000000E8`がアーカイブされていないことに気づく。

47/E6000000` から `47/E9000000` にジャンプしている。


ここで起こるべきことは、レプリケーションスロットの `restart_lsn` から再開することである。

から再開することである。


## 新機能: `READ_REPLICATION_SLOT` コマンド


バージョン15以前のPostgreSQLでは、レプリケーションスロットの位置を知る唯一の方法は

pg_replication_slots`ビューに問い合わせるしかありませんでした。

ビューに問い合わせることでした。これは論理レプリケーションでは問題ありません。

接続はデータベースにバインドされており、SQLクエリの実行が許可されているからです。しかし

物理レプリケーション接続の場合、[この可能性はありません](https://www.postgresql.org/docs/14/protocol-replication.html)


つまり、物理レプリケーション・クライアントは

レプリケーションスロットの状態を知る方法がないことを意味します、

これは `pg_receivewal` アプリケーションでできることではありません。


READ_REPLICATION_SLOT`コマンドはこのギャップを埋めることを目的としている。

レプリケーション接続は、現在の `restart_lsn` とそれに関連するタイムラインを読み込むことができます。

をレプリケーションスロットに関連付けることができます：



```
 `❯ psql postgres -d "replication=1"
psql (15devel)
 help" と入力するとヘルプが表示されます。
 postgres=# READ_REPLICATION_SLOT slot1；
 slot_type | restart_lsn | restart_tli
 -----------+-------------+-------------
 物理｜0/1501000｜1
(1行)``クリップボードにコピー
```

この新しいコマンドによって、`pg_receivewal`は開始LSNを決定できるようになりました。

を決定できるようになった：


* アーカイブフォルダにどのようなセグメントがあるかを見て、そのセグメントから再開する。

アーカイブされた最新のものから再開する。
* アーカイブ・フォルダーが空で、レプリケーション・スロットが使用されている場合、

READ_REPLICATION_SLOT`コマンドを発行して、サーバーから状態を読み込む。
* そうでない場合は、サーバーの現在のLSNからストリーミングを開始する。


この新しいコマンドは現在、物理レプリケーション・スロットでのみサポートされています、

この新しいコマンドは現在、物理的なレプリケーション・スロットに対してのみサポートされており、限られた情報しか返しませんが、必要であれば将来的に進化する可能性があります。  

この機能は、すでに

pg_receivewal`を使用したときに遭遇した "驚き "を解決するのに役立ちます。

他のレプリケーションクライアントにも役立つだろう。この機能はプロジェクトに採用され、今後

バージョン15のリリースで利用可能になる予定である。


## 次のステップ


* [Aiven for PostgreSQL](https://aiven.io/postgresql)の詳細、または[無料トライアルに申し込む](https://console.aiven.io/signup)。
* [GitHubのPgHoardプロジェクト](https://github.com/aiven/pghoard)をチェックしてください。
* 私たちの[OSPO](https://aiven.io/open-source)(オープンソース・プログラム・オフィス)の他の活動もご覧ください。
* [Twitter](https://twitter.com/aiven_io)をフォローして、このような投稿をチェックしてください。