diff options
author | Amit Kapila <akapila@postgresql.org> | 2024-08-20 08:35:11 +0530 |
---|---|---|
committer | Amit Kapila <akapila@postgresql.org> | 2024-08-20 08:35:11 +0530 |
commit | 9758174e2e5cd278cf37e0980da76b51890e0011 (patch) | |
tree | 9ca019972be8f6b4b20acd98cdeb12a9475851e9 /doc/src | |
parent | adf97c1562380e02acd60dc859c289ed3a8352ee (diff) | |
download | postgresql-9758174e2e5cd278cf37e0980da76b51890e0011.tar.gz postgresql-9758174e2e5cd278cf37e0980da76b51890e0011.zip |
Log the conflicts while applying changes in logical replication.
This patch provides the additional logging information in the following
conflict scenarios while applying changes:
insert_exists: Inserting a row that violates a NOT DEFERRABLE unique constraint.
update_differ: Updating a row that was previously modified by another origin.
update_exists: The updated row value violates a NOT DEFERRABLE unique constraint.
update_missing: The tuple to be updated is missing.
delete_differ: Deleting a row that was previously modified by another origin.
delete_missing: The tuple to be deleted is missing.
For insert_exists and update_exists conflicts, the log can include the origin
and commit timestamp details of the conflicting key with track_commit_timestamp
enabled.
update_differ and delete_differ conflicts can only be detected when
track_commit_timestamp is enabled on the subscriber.
We do not offer additional logging for exclusion constraint violations because
these constraints can specify rules that are more complex than simple equality
checks. Resolving such conflicts won't be straightforward. This area can be
further enhanced if required.
Author: Hou Zhijie
Reviewed-by: Shveta Malik, Amit Kapila, Nisha Moond, Hayato Kuroda, Dilip Kumar
Discussion: https://postgr.es/m/OS0PR01MB5716352552DFADB8E9AD1D8994C92@OS0PR01MB5716.jpnprd01.prod.outlook.com
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/logical-replication.sgml | 103 |
1 files changed, 98 insertions, 5 deletions
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml index a23a3d57e2b..885a2d70ae7 100644 --- a/doc/src/sgml/logical-replication.sgml +++ b/doc/src/sgml/logical-replication.sgml @@ -1579,8 +1579,91 @@ test_sub=# SELECT * FROM t1 ORDER BY id; node. If incoming data violates any constraints the replication will stop. This is referred to as a <firstterm>conflict</firstterm>. When replicating <command>UPDATE</command> or <command>DELETE</command> - operations, missing data will not produce a conflict and such operations - will simply be skipped. + operations, missing data is also considered as a + <firstterm>conflict</firstterm>, but does not result in an error and such + operations will simply be skipped. + </para> + + <para> + Additional logging is triggered in the following <firstterm>conflict</firstterm> + cases: + <variablelist> + <varlistentry> + <term><literal>insert_exists</literal></term> + <listitem> + <para> + Inserting a row that violates a <literal>NOT DEFERRABLE</literal> + unique constraint. Note that to log the origin and commit + timestamp details of the conflicting key, + <link linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link> + should be enabled on the subscriber. In this case, an error will be + raised until the conflict is resolved manually. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>update_differ</literal></term> + <listitem> + <para> + Updating a row that was previously modified by another origin. + Note that this conflict can only be detected when + <link linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link> + is enabled on the subscriber. Currenly, the update is always applied + regardless of the origin of the local row. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>update_exists</literal></term> + <listitem> + <para> + The updated value of a row violates a <literal>NOT DEFERRABLE</literal> + unique constraint. Note that to log the origin and commit + timestamp details of the conflicting key, + <link linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link> + should be enabled on the subscriber. In this case, an error will be + raised until the conflict is resolved manually. Note that when updating a + partitioned table, if the updated row value satisfies another partition + constraint resulting in the row being inserted into a new partition, the + <literal>insert_exists</literal> conflict may arise if the new row + violates a <literal>NOT DEFERRABLE</literal> unique constraint. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>update_missing</literal></term> + <listitem> + <para> + The tuple to be updated was not found. The update will simply be + skipped in this scenario. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>delete_differ</literal></term> + <listitem> + <para> + Deleting a row that was previously modified by another origin. Note that + this conflict can only be detected when + <link linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link> + is enabled on the subscriber. Currenly, the delete is always applied + regardless of the origin of the local row. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>delete_missing</literal></term> + <listitem> + <para> + The tuple to be deleted was not found. The delete will simply be + skipped in this scenario. + </para> + </listitem> + </varlistentry> + </variablelist> + Note that there are other conflict scenarios, such as exclusion constraint + violations. Currently, we do not provide additional details for them in the + log. </para> <para> @@ -1597,7 +1680,7 @@ test_sub=# SELECT * FROM t1 ORDER BY id; </para> <para> - A conflict will produce an error and will stop the replication; it must be + A conflict that produces an error will stop the replication; it must be resolved manually by the user. Details about the conflict can be found in the subscriber's server log. </para> @@ -1609,8 +1692,9 @@ test_sub=# SELECT * FROM t1 ORDER BY id; an error, the replication won't proceed, and the logical replication worker will emit the following kind of message to the subscriber's server log: <screen> -ERROR: duplicate key value violates unique constraint "test_pkey" -DETAIL: Key (c)=(1) already exists. +ERROR: conflict detected on relation "public.test": conflict=insert_exists +DETAIL: Key already exists in unique index "t_pkey", which was modified locally in transaction 740 at 2024-06-26 10:47:04.727375+08. +Key (c)=(1); existing local tuple (1, 'local'); remote tuple (1, 'remote'). CONTEXT: processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 0/14C0378 </screen> The LSN of the transaction that contains the change violating the constraint and @@ -1636,6 +1720,15 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER Please note that skipping the whole transaction includes skipping changes that might not violate any constraint. This can easily make the subscriber inconsistent. + The additional details regarding conflicting rows, such as their origin and + commit timestamp can be seen in the <literal>DETAIL</literal> line of the + log. But note that this information is only available when + <link linkend="guc-track-commit-timestamp"><varname>track_commit_timestamp</varname></link> + is enabled on the subscriber. Users can use this information to decide + whether to retain the local change or adopt the remote alteration. For + instance, the <literal>DETAIL</literal> line in the above log indicates that + the existing row was modified locally. Users can manually perform a + remote-change-win. </para> <para> |