Exploring conflict handling with PGD

PGDのようなマルチマスターアーキテクチャでは、競合が発生します。 PGDはそれらを処理するように構築されています。

1つのデータベースノードでアプリケーションから行への更新があり、別のノードで同じ行への別の更新がある場合、競合が発生する可能性があります。このタイプの競合は、 行レベルの競合 と呼ばれます。競合はエラーではありません。それらを効果的に解決することは、 Postgres Distributedが一貫性を維持する方法の中核です。

コンフリクトを処理する最良の方法は、そもそもコンフリクトを持たないことです!プロキシでPGDのAlways-Onアーキテクチャを使用して、アプリケーションがクラスター内の同じサーバーに書き込むようにします。

ただし、競合が発生した場合、PGDが競合を解決する方法、その解決を制御する方法、および競合が発生していることを確認する方法を知っておくと役立ちます。行の挿入と行の更新は、競合を引き起こす可能性のある2つのアクションです。

それがどのように機能するかを確認するには、すべてのサーバーのコマンドラインビューを開く必要があります。

クイックスタート構成

この探索では、 quick start for Docker 、 quick start for AWS 、または quick start for Linux hosts を使用してPGDクラスターを作成したことを前提としています。

各クイックスタートの最後には、4つのノードと次のロールを持つクラスターが作成されます。

Host name

Host role

kaboom

PGD data node and pgd-proxy co-host

kaftan

PGD data node and pgd-proxy co-host

kaolin

PGD data node and pgd-proxy co-host

kapok

Barman backup node

この演習では、これらのホスト名を使用します。

xpanesのインストール

xpanes を使用します。これは、簡単に切り替えることができる複数のターミナルセッションをすばやく作成できるユーティリティです。デフォルトではインストールされないため、インストールする必要があります。 sshでkaboomノードに接続することから始めます。

cd democluster && ssh -F ssh_config kaboom

Dockerでクイックスタートを実行している場合、Red Hatの派生物であるRocky Linuxを使用します。 xpanesのインストールを実行するには、次を実行します。

dnf -y install xpanes

AWSでクイックスタートを実行している場合、Debian Linuxを使用します。 xpanesのインストールを実行するには、次を実行します。

wget https://github.com/greymd/tmux-xpanes/releases/download/v4.1.4/tmux-xpanes_v4.1.4.deb
sudo apt -y install ./tmux-xpanes*.deb
rm tmux-xpanes*.deb

4つのサーバーへの接続

認証を機能させるには、enterprisedbユーザーとしてログインする必要があります。

sudo -iu enterprisedb

次に、次のコマンドを実行して、3つのデータベースサーバーとプロキシサーバーに接続します。

xpanes -d -c "psql postgresql://enterprisedb@{}/bdrdb?sslmode=require" "kaboom:5444" "kaftan:5444" "kaolin:5444" "kaboom:6432"

xpanesは-c の後のコマンドを受け取り、続く引数の値を使用して、実行するコマンドを作成します。つまり、実行すると4つのペインが表示されます。 3つのペインがポート5444のデータベースノードkaboom、kaftan、およびkaolinに接続されます。1つはポート6432のkaboomで実行されているpgd-proxyに接続されます。それぞれがenterprisedbとしてデータベースにログインします。

Control-b を押してから q を押して、各ペインの数値を簡単に表示します。

4 Sessions showing numbers

4 Sessions showing numbers

ペイン間でフォーカスを切り替えるには、 Control-b とカーソルキーを使用してペイン間を移動できます。または、 Control-b を使用し、その後に q とフォーカスするペインの番号を入力します。両方の方法を示します。

Control-b↓を使用して左下のペインに移動します。Control-b→または Control-b q 3**。

衝突の準備

競合を起こすには、最初に単純なテーブルが必要です。現在フォーカスがあるペインで、次のように入力します。

drop table if exists test_conflict;
create table test_conflict(
  id integer primary key ,
  value_1 text);

競合の監視

現在フォーカスがあるペインで、次のように入力します。

select * from bdr.conflict_history_summary
\watch 1

select コマンドは、クラスターの競合履歴を表示します。 \watch 1 コマンドは、前述のコマンドを1秒ごとに再実行するpsqlコマンドです。

これで、競合を生成する準備が整いました。

競合の作成

最も基本的な競合の形態は、2つの異なるノード上のテーブルに挿入が発生し、両方が同じ主キーを持つ場合です。そのシナリオを作成して観察できるようになりました。

Control-b↑を使用して左上のペインに移動しますControl-b← または Control-bq0 。このペインはkaboomノードです。そこでトランザクションを開始し、行を挿入します。

start transaction;
insert into test_conflict values (1, from kaboom);

次に、 Control-b→ または Control-bq1 を使用して、右上のペインに移動します。このペインはkaftanノードです。ここでも、トランザクションを開始し、異なるデータを同じ行に挿入します。

start transaction;
insert into test_conflict values (1, from kaftan);

これで、異なるサーバーで2つのトランザクションが開かれ、挿入操作が既に正常に実行されました。この時点で両方のトランザクションをコミットする必要があります。

*** Control-b ← または Control-b q 0**を使用して、 commit; と入力します。

*** Control-b → または Control-b q 1**を使用し、 commit; と入力します。

両方のコミットが機能していることがわかります。ただし、右下のペインでは、競合が検出されていることを確認できます。

4 Sessions showing conflict detected

4 Sessions showing conflict detected

競合履歴の行に、 insert_exists .また、この競合の解決は、コミットのタイミングに基づいて、より新しいレコードが保持されることであることに注意してください。この競合は、 INSERT / INSERT競合と呼ばれます。このタイプの競合の詳細については、

INSERT / INSERTの競合 を参照してください。

更新の競合の作成

同じレコードに対する異なる更新が異なるノードで行われると、競合が発生します。現在の構成でそのシナリオを作成することもできます。右下のペインで\watch 1 を実行したままにします。

Control-b← または Control-bq0 を使用して、左上のペインに移動します。このペインはkaboomノードです。ここで、トランザクションを開始し、行を更新します。

start transaction;
update test_conflict set value_1 = update from kaboom where id = 1;

次に、 Control-b→ または Control-bq1 を使用して、右上のペインに移動します。このペインはkaftanノードです。ここでも、トランザクションを開始し、同じ行を異なるデータで更新します。

start transaction;
update test_conflict set value_1 = update from kaftan where id = 1;

これで、異なるサーバーで2つのトランザクションが開かれ、更新操作が既に正常に実行されました。この時点で両方のトランザクションをコミットする必要があります。

*** Control-b cursor-left または Control-b q 0**を使用し、 commit; と入力します。

*** Control-b cursor-right または Control-b q 1**を使用し、 commit; と入力します。

繰り返しますが、両方のコミットが機能していることがわかります。そして、再び、右下のペインで、更新の競合が検出されていることを確認できます。

4 Sessions showing update conflict detected

4 Sessions showing update conflict detected

競合履歴の追加の行は、update_origin_change 競合が発生し、解決がapply_remote であったことを示しています。この解決は、リモート変更が適用され、レコードが更新されたことを意味します。この競合は UPDATE / UPDATE競合と呼ばれ、 UPDATE / UPDATEの競合 で詳しく説明されています。

!!!Tip Tmuxの終了 Tmuxと関連するすべてのセッションをすばやく終了できます。セッションが強制終了された後も実行を継続するため、最初に実行中のプロセスを終了します。 Control-b を押してから、 :kill-session と入力します。このアプローチは、 Control-D またはexit を使用して各ペインのセッションを1つずつ終了するよりも簡単です。

これで、考えられるすべての競合シナリオと発生する可能性のある解決策を探索する準備が整いました。競合の管理方法の詳細については、ドキュメントの CRDTデータ型を使用した列の競合の処理 を参照してください。理想的には、競合を避けるべきですが、競合が発生すると、Postgres Distributedの統合され構成可能な競合リゾルバーによって記録および管理されることを知っておくことが重要です。