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つのデータベースサーバーと1つのプロキシサーバーに接続します。

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-プロキシに接続されます。それぞれは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 コマンドは、前述のコマンドを毎秒再実行するpsqlコマンドです。

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

競合の作成#

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

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

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

次に、 Control-b → または Control-b q 1 を使用して右上ペインに移動します。このペインは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-b q 0 を使用して、左上のペインに移動します。このペインはkaboomノードです。ここで、トランザクションを開始し、行を更新します。

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

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

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

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

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

  • Control-b rotation-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の競合 で詳細に説明します。

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

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