Timestamps in column-level conflict resolution#

列レベルの競合の解決は、テーブルに含まれるタイムスタンプ列によって異なります。

column_modify_timestamp とcolumn_commit_timestamp の比較#

2つの列レベルの競合検出方法のいずれかを選択すると、変更された列とタイムスタンプのマッピングを含む列がテーブルに追加されます。

タイムスタンプマッピングを格納する列は自動的に管理されます。結果は予測できない場合があるため、クエリーで値を指定またはオーバーライドしないでください。可能な場合、ユーザーが値をオーバーライドしようとしても無視されます。

テーブルの列タイムスタンプを有効または無効にする場合、コードはDDLロックを使用して、スイッチ前からの保留中の変更がないことを確認します。このアプローチでは、両方のタプルのタイムスタンプと競合のみが表示されないようにします。そうしないと、コードは予期せずローカルタプルのタイムスタンプとリモートタプルのNULLを認識する場合があります。また、変更がすべてのノードで同じ方法列レベルまたは行レベルで解決されることも保証します。

column_modify_timestamp#

競合検出方法としてcolumn_modify_timestamp が選択されている場合、変更された列に割り当てられたタイムスタンプは、現在のタイムスタンプであり、select_clock_timestamp() を実行して取得する値と似ています。

このアプローチは簡単で、多くの場合、たとえば、競合する行が列の重複しないサブセットを変更する場合、それは正しいです。ただし、そのシンプルさは予期しない効果をもたらす可能性があります。

たとえば、 UPDATE が複数の行に影響を与える場合、UPDATE の実行中クロックは刻み続けます。したがって、各行は、UPDATE によって同時に変更されている場合でも、わずかに異なるタイムスタンプを取得します。この動作は、さまざまなノードで実行される変更がどのようにインターリーブされるかに応じて、同時の変更のエフェクトがさまざまな方法で「混合」される可能性があることを意味します。

もう1つ考えられる問題は、クロックスキューです。別のノードのクロックがドリフトすると、それらのノードによって生成されたタイムスタンプもドリフトします。このクロックスキューは、タイムスタンプが明らかに切り替わっているため、新しい変更が破棄されるなどの予期しない動作を誘発する可能性があります。ただし、パラメーター bdr.maximum_clock_skew および bdr.maximum_clock_skew_action を使用してノード間のクロックスキューを管理できます。

現在のタイムスタンプはコミットタイムスタンプと無関係であるため、競合の解決にそれを使用することは、結果がコミット順序と等価ではないこと、つまりシリアル化できないことを意味します。

現在のタイムスタンプを使用して変更またはコミットを注文する場合、2つ以上のノードがたまたま同じタイムスタンプを生成したため、競合する変更のタイムスタンプがまったく同じになる場合があります。このリスクは、通常の行レベルの競合解決でも発生する可能性があるため、列レベルの競合解決に固有ではありません。この状況では、ノードIDがタイブレーカーとして使用されます。ノードIDが高い方が優先します。このアプローチでは、すべてのノードに同じ変更が適用されます。

column_commit_timestamp#

column_commit_timestamp で指定された実際のコミットタイムスタンプを競合検出方法として使用することもできます。このアプローチには、UPDATE で行われたすべての変更で同じであるコミット時間を使用する利点があります。

注釈

将来的にステートメントトランザクションが追加される可能性があります。これにより、コンカレントステートメントまたはトランザクションの混合効果に関する問題が解決されます。それでも、これらのオプションはいずれも、コミットオーダーと同等の結果を生成することはできません。

カラムのタイムスタンプの検査#

変更された列のタイムスタンプを格納する列は、トリガーによって維持されます。直接変更しないでください。たとえば、競合がどのように解決されたかを調査しているときに、現在のタイムスタンプの値を検査すると役立つ場合があります。

注釈

タイムスタンプマッピングはトリガーによって維持され、トリガーの実行順序が重要です。カスタムトリガーがタプルを変更し、 pgl_clcd_トリガーの後に実行される場合、変更された列は正しく検出されません。これにより、誤った競合解決が発生する可能性があります。トリガー内のタプルを変更する必要がある場合は、 pgl_clcd_トリガーの前に実行されていることを確認します。

次の機能は、タイムスタンプを検査するために役立ちます。

bdr.column_timestamps_to_text(bdr.column_timestamps)#

このファンクションは、タイムスタンプマッピングの人間が判読可能な表現を返し、値をテキストにキャストするときに使用されます。

db=# select cts::text from test_table;
                                                 cts
- ----------------------------------------------------------------------------------------------------
 {source: current, default: 2018-09-23 19:24:52.118583+02, map: [2 : 2018-09-23 19:25:02.590677+02]}
(1 row)

bdr.column_timestamps_to_jsonb(bdr.column_timestamps)#

このファンクションは、タイムスタンプマッピングのJSONB表現を変換し、値をjsonbにキャストするときに使用されます。

db=# select jsonb_pretty(cts::jsonb) from test_table;
                   jsonb_pretty
- --------------------------------------------------
 {                                                +
     "map": {                                     +
         "2": "2018-09-23T19:24:52.118583+02:00"  +
     },                                           +
     "source": "current",                         +
     "default": "2018-09-23T19:24:52.118583+02:00"+
 }
(1 row)

bdr.column_timestamps_resolve(bdr.column_timestamps, xid)#

このファンクションは、最新のトランザクションが既にコミットしている場合、それによって変更された属性のコミットタイムスタンプを使用してマッピングを更新します。これは、コミットタイムスタンプを使用する場合にのみ重要です。たとえば、この場合、最後のトランザクションは2番目の属性を更新しましたattnum = 2

test=# select cts::jsonb from test_table;
                                                                  cts
- ---------------------------------------------------------------------------------------------------------------------------------------
 {"map": {"2": "2018-09-23T19:29:55.581823+02:00"}, "source": "commit", "default": "2018-09-23T19:29:55.581823+02:00", "modified": [2]}
(1 row)

db=# select bdr.column_timestamps_resolve(cts, xmin)::jsonb from test_table;
                                               column_timestamps_resolve
- ----------------------------------------------------------------------------------------------------------------------
 {"map": {"2": "2018-09-23T19:29:55.581823+02:00"}, "source": "commit", "default": "2018-09-23T19:29:55.581823+02:00"}
(1 row)