PostgreSQL14でのXNUMXフェーズコミットの論理デコードテキスト

更新:2年2023月XNUMX日

PostgreSQL14でのXNUMXフェーズコミットの論理デコードテキスト

富士通OSSチームとPostgreSQLオープンソースコミュニティは協力して、PG14の論理レプリケーションでXNUMXフェーズコミットを復号化する機能を追加しました。 この機能とは何かを見てみましょう。

背景

XNUMX フェーズ コミットは、トランザクションを XNUMX つのフェーズでコミットするメカニズムです。 通常、分散データベースで一貫性を確保するために使用されます。 トランザクションの XNUMX つのフェーズは、PREPARE フェーズと COMMIT/ROLLBACK フェーズです。 PG の XNUMX つのフェーズで送信されるコマンドは次のとおりです。

トランザクションの準備

コミット準備済み

ロールバック準備済み

PG はバージョン 8.0 ですでに 10.0 フェーズ コミットをサポートしており、バージョン XNUMX では論理レプリケーションをサポートしています。 ただし、XNUMX フェーズ コミットは論理レプリケーションではサポートされていません。 PREPARE TRANSACTION、COMMIT PREPARED、および ROLLBACK PREPARED コマンドは単一インスタンスでサポートされていますが、これらのコマンドをスタンバイ マシンに論理的にコピーする必要がある場合、元の意味は維持されなくなります。 PREPARE TRANSACTION コマンドは NOP として扱われ、まったくデコードされません。 COMMIT PREPARED コマンドは COMMIT とみなされ、ROLLBACK PREPARED コマンドは ABORT とみなされます。

XNUMXフェーズコミットとは何ですか

XNUMXフェーズコミットは、分散データベース間の一貫性を維持するのに役立つアトミックコミットプロトコルです。 データベース内でアトミック性を提供する通常のコミットは、データベース間トランザクションの一貫性を提供するのに十分ではありません。 この問題を説明するために、例を挙げましょう。

1)ジョンは銀行Aに300ドルを持っています

2)マークは銀行Bに100 $を持っています

3)ジョンは100ドルをマークに送金したい

取引中に、銀行Aから銀行Bに100ドルを引き出す必要があります。取引の最後に、200ドルが必要です。 転送プロセス中にトランザクションが失敗した場合は、アカウントのステータスを転送開始前の状態に復元する必要があります。 トランザクションはさまざまな理由で失敗する可能性があります。 トランザクションがコミットする前に中断が発生した場合、トランザクションはロールバックされます。 この例では、ジョンのアカウントが差し引かれたときに中断が発生した場合、中断ポートのジョンのアカウントを減らすべきではありません。 これは、単純なコミットがデータベース内の一貫性を維持する方法です。

しかし、このような状況を考えます。つまり、ジョンの口座から 100 ドルを差し引くトランザクションは 100 回の送信で成功しますが、銀行 B のマークの口座に 100 ドルを追加するトランザクションは失敗し、ロールバックされたとします。 この操作が終了すると、ジョンの口座から引き落とされますが、マークはその金額を受け取ることはできません。 XNUMXドルが消えた。 分散トランザクションを扱う場合、単純なコミットが失敗する可能性があります。

分散トランザクションの段階的な実行

XNUMXフェーズコミットの場合、データベースのXNUMXつが分散トランザクションのコーディネーターとして機能します。

ステージ1

データベースはトランザクションの適用を開始し、準備を始めます。 準備されたトランザクションを準備メッセージの形式で他のデータベースに送信します。 XNUMX 番目のデータベースは Prepare メッセージを取得し、トランザクションを準備します。 Prepare にはトランザクションの変更が含まれますが、コミットはしません。 ダーティ データは永続化のためにディスクに書き込まれます。 すべてのデータベースがトランザクションを準備し、トランザクションに関するすべての情報がディスクに保存されると、準備フェーズは完了します。

ステージ2

次に、アービターはコミットフェーズを開始します。 XNUMX番目のデータベースが何らかの理由でトランザクションの準備に失敗した場合、アービターはロールバックフェーズを開始します。 したがって、準備が成功したかどうかに応じて、トランザクションはコミットまたはロールバックされます。 必要な準備トランザクションがディスクに書き込まれ、再適用できるため、最終コミットフェーズでの中断を回復できます。

XNUMXフェーズコミットは単一インスタンスデータベースとは関係ありませんが、データが複数のデータベースインスタンス間で複製される場合は関係があります。

論理レプリケーションでXNUMXフェーズコミットをサポートすることは非常に重要です。

機能概要

PG14バージョンより前は、論理レプリケーショントランザクションは、トランザクションがコミットされた後にのみデコードおよびレプリケートされていました。 これは、レプリケーショントランザクションが最終的に中止される可能性を回避するためです。

コミット時にトランザクションをデコードする

PG14 の論理レプリケーションは、PREPARE TRANSACTION、COMMIT PREPARED、および ROOLBACK PREPARED コマンドをサポートします。 PREPARE TRANSACTION コマンドがデコードされると、トランザクションがデコードされてコピーされます。 PREPARE TRANSACTION は、WAL SENDER の COMMIT と同様に、トランザクションの再生とデコードを開始します。

準備中のデコードトランザクション

また、論理デコードプラグインがXNUMXフェーズ送信をサポートできるように、新しいプラグインコールバックを定義しました。

コー​​ルバック

説明する

filter_prepare_cb

PREPARE TRANSACTIONコマンドで使用されるGIDに従って準備するときに、デコードする必要のないトランザクションをプラグインがフィルタリングできるようにします。

begin_prepare_cb

準備トランザクションの開始

prepare_cb

PREPARETRANSACTIONコマンドがデコードされたときに呼び出されます

commit_prepared_cb

COMMITPREPAREDコマンドがデコードされたときに呼び出されます

rollback_prepared_cb

ROLLBACKPREPAREDコマンドがデコードされたときに呼び出されます

プラグインの変更

test_decoding

このプラグインは、ユーザーが独自の論理デコード プラグインを開発するのに役立つ例として、論理デコード出力プラグインです。 test_decoding は、論理デコード メカニズムを通じて WAL を受信し、実行された操作のテキスト表現にデコードします。

新しいXNUMX段階のコールバック関数を使用し、準備中にトランザクションをデコードできるように変更されました

APIの変更

pg_create_logical_replication_slot()

APIは、スロットがXNUMXフェーズコミットをサポートするかどうかを指定する新しいオプションを追加します。 出力プラグインは、XNUMXフェーズオプション付きのレプリケーションスロットを使用して、XNUMXフェーズコミットをサポートできます。

pg_create_logical_replication_slot(slot_name name、plugin name [、temporary boolean、two_phase boolean])

ケーススタディ

XNUMXフェーズコミットトランザクションのデコードされた出力を検出する方法を見てみましょう。

1)レプリケーションスロットを作成します

test_decodingを出力プラグインとして使用し、trueを渡して、スロットがXNUMX段階の送信とデコードをサポートするようにします。

postgres =#SELECT * FROM pg_create_logical_replication_slot( 'regression_slot'、 'test_decoding'、false、true);

slot_name {XNUMX} lsn

--------------------------------------------------------------------------------------------------------------------

リグレッション_スロット@ 0 / 16B1970

(1列)

2)テーブルを作成します

postgres =#CREATE TABLEデータ(IDシリアル主キー、データテキスト);

テーブルを作成

3)準備トランザクションとコミットトランザクションのデコードされた出力コンテンツを検出します

postgres =#BEGIN;

postgres = *#IN​​SERT INTO data(data)VALUES( '5');

postgres = *#PREPARETRANSACTION'test_prepared1 ';

postgres =#SELECT * FROM pg_logical_slot_get_changes( 'regression_slot'、NULL、NULL);

lsn {XNUMX} xid❤データ

---------------------------------------------------------------------------------------------------------------------------------------

0 / 1689DC0 @ 529 @ BEGIN 529

0 / 1689DC0 @ 529 セ table public.data:INSERT:id [in​​teger]:3 data [text]: '5'

0 / 1689FC0 @ 529 @ PREPARE TRANSACTION'test_prepared1 '、txid 529

(3列)

postgres =#COMMITPREPARED'test_prepared1 ';

postgres =#select * from pg_logical_slot_get_changes( 'regression_slot'、NULL、NULL);

lsn {XNUMX} xid❤データ

----------- + ------ + ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0 / 168A060 _ 529 _ COMMIT PREPARED'test_prepared1 '、txid 529

(4列)

postgres =#データから*を選択;

id❤データ

---- + -------

1 セ 5

(1列)

未来

この機能に対するPG14の変更には、準備中にデコードをXNUMX段階で送信できるデコーダー側のインフラストラクチャがあります。 また、このインフラストラクチャを利用するようにtest_decodingプラグインを変更しました。

次のステップは、PGで最大の論理デコードプラグインであるpgoutputプラグインに15段階のサポートを実装することです。 このプラグインは、論理レプリケーションのPUBLISHER / SUBSCRIBERモードをサポートします。 これは、論理レプリケーションで最も広く使用されているプラ​​グインです。 富士通OSSチームは、オープンソースコミュニティと協力して、この機能をPGXNUMXに追加しています。

分散データベースのXNUMXフェーズトランザクションの場合、PGもサポートする必要があります。スタンバイマシンは、PREPAREが失敗したことをホストに通知し、ロールバックを開始します。 このフィードバックメカニズムはPGではサポートされておらず、将来の改善の方向性のXNUMXつです。

  リンク:

6mbi25l-120

rm500uz-2h