]> begriffs open source - ai-pg/blob - full-docs/txt/logical-replication-conflicts.txt
Convert HTML docs to more streamlined TXT
[ai-pg] / full-docs / txt / logical-replication-conflicts.txt
1
2 29.7. Conflicts #
3
4    Logical replication behaves similarly to normal DML operations in that
5    the data will be updated even if it was changed locally on the
6    subscriber node. If incoming data violates any constraints the
7    replication will stop. This is referred to as a conflict. When
8    replicating UPDATE or DELETE operations, missing data is also
9    considered as a conflict, but does not result in an error and such
10    operations will simply be skipped.
11
12    Additional logging is triggered, and the conflict statistics are
13    collected (displayed in the pg_stat_subscription_stats view) in the
14    following conflict cases:
15
16    insert_exists #
17           Inserting a row that violates a NOT DEFERRABLE unique
18           constraint. Note that to log the origin and commit timestamp
19           details of the conflicting key, track_commit_timestamp should be
20           enabled on the subscriber. In this case, an error will be raised
21           until the conflict is resolved manually.
22
23    update_origin_differs #
24           Updating a row that was previously modified by another origin.
25           Note that this conflict can only be detected when
26           track_commit_timestamp is enabled on the subscriber. Currently,
27           the update is always applied regardless of the origin of the
28           local row.
29
30    update_exists #
31           The updated value of a row violates a NOT DEFERRABLE unique
32           constraint. Note that to log the origin and commit timestamp
33           details of the conflicting key, track_commit_timestamp should be
34           enabled on the subscriber. In this case, an error will be raised
35           until the conflict is resolved manually. Note that when updating
36           a partitioned table, if the updated row value satisfies another
37           partition constraint resulting in the row being inserted into a
38           new partition, the insert_exists conflict may arise if the new
39           row violates a NOT DEFERRABLE unique constraint.
40
41    update_missing #
42           The row to be updated was not found. The update will simply be
43           skipped in this scenario.
44
45    delete_origin_differs #
46           Deleting a row that was previously modified by another origin.
47           Note that this conflict can only be detected when
48           track_commit_timestamp is enabled on the subscriber. Currently,
49           the delete is always applied regardless of the origin of the
50           local row.
51
52    delete_missing #
53           The row to be deleted was not found. The delete will simply be
54           skipped in this scenario.
55
56    multiple_unique_conflicts #
57           Inserting or updating a row violates multiple NOT DEFERRABLE
58           unique constraints. Note that to log the origin and commit
59           timestamp details of conflicting keys, ensure that
60           track_commit_timestamp is enabled on the subscriber. In this
61           case, an error will be raised until the conflict is resolved
62           manually.
63
64    Note that there are other conflict scenarios, such as exclusion
65    constraint violations. Currently, we do not provide additional details
66    for them in the log.
67
68    The log format for logical replication conflicts is as follows:
69 LOG:  conflict detected on relation "schemaname.tablename": conflict=conflict_ty
70 pe
71 DETAIL:  detailed_explanation.
72 {detail_values [; ... ]}.
73
74 where detail_values is one of:
75
76     Key (column_name [, ...])=(column_value [, ...])
77     existing local row [(column_name [, ...])=](column_value [, ...])
78     remote row [(column_name [, ...])=](column_value [, ...])
79     replica identity {(column_name [, ...])=(column_value [, ...]) | full [(colu
80 mn_name [, ...])=](column_value [, ...])}
81
82    The log provides the following information:
83
84    LOG
85
86           + schemaname.tablename identifies the local relation involved in
87             the conflict.
88           + conflict_type is the type of conflict that occurred (e.g.,
89             insert_exists, update_exists).
90
91    DETAIL
92
93           + detailed_explanation includes the origin, transaction ID, and
94             commit timestamp of the transaction that modified the existing
95             local row, if available.
96           + The Key section includes the key values of the local row that
97             violated a unique constraint for insert_exists, update_exists
98             or multiple_unique_conflicts conflicts.
99           + The existing local row section includes the local row if its
100             origin differs from the remote row for update_origin_differs
101             or delete_origin_differs conflicts, or if the key value
102             conflicts with the remote row for insert_exists, update_exists
103             or multiple_unique_conflicts conflicts.
104           + The remote row section includes the new row from the remote
105             insert or update operation that caused the conflict. Note that
106             for an update operation, the column value of the new row will
107             be null if the value is unchanged and toasted.
108           + The replica identity section includes the replica identity key
109             values that were used to search for the existing local row to
110             be updated or deleted. This may include the full row value if
111             the local relation is marked with REPLICA IDENTITY FULL.
112           + column_name is the column name. For existing local row, remote
113             row, and replica identity full cases, column names are logged
114             only if the user lacks the privilege to access all columns of
115             the table. If column names are present, they appear in the
116             same order as the corresponding column values.
117           + column_value is the column value. The large column values are
118             truncated to 64 bytes.
119           + Note that in case of multiple_unique_conflicts conflict,
120             multiple detailed_explanation and detail_values lines will be
121             generated, each detailing the conflict information associated
122             with distinct unique constraints.
123
124    Logical replication operations are performed with the privileges of the
125    role which owns the subscription. Permissions failures on target tables
126    will cause replication conflicts, as will enabled row-level security on
127    target tables that the subscription owner is subject to, without regard
128    to whether any policy would ordinarily reject the INSERT, UPDATE,
129    DELETE or TRUNCATE which is being replicated. This restriction on
130    row-level security may be lifted in a future version of PostgreSQL.
131
132    A conflict that produces an error will stop the replication; it must be
133    resolved manually by the user. Details about the conflict can be found
134    in the subscriber's server log.
135
136    The resolution can be done either by changing data or permissions on
137    the subscriber so that it does not conflict with the incoming change or
138    by skipping the transaction that conflicts with the existing data. When
139    a conflict produces an error, the replication won't proceed, and the
140    logical replication worker will emit the following kind of message to
141    the subscriber's server log:
142 ERROR:  conflict detected on relation "public.test": conflict=insert_exists
143 DETAIL:  Key already exists in unique index "t_pkey", which was modified locally
144  in transaction 740 at 2024-06-26 10:47:04.727375+08.
145 Key (c)=(1); existing local row (1, 'local'); remote row (1, 'remote').
146 CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
147 T" for replication target relation "public.test" in transaction 725 finished at
148 0/14C0378
149
150    The LSN of the transaction that contains the change violating the
151    constraint and the replication origin name can be found from the server
152    log (LSN 0/14C0378 and replication origin pg_16395 in the above case).
153    The transaction that produced the conflict can be skipped by using
154    ALTER SUBSCRIPTION ... SKIP with the finish LSN (i.e., LSN 0/14C0378).
155    The finish LSN could be an LSN at which the transaction is committed or
156    prepared on the publisher. Alternatively, the transaction can also be
157    skipped by calling the pg_replication_origin_advance() function. Before
158    using this function, the subscription needs to be disabled temporarily
159    either by ALTER SUBSCRIPTION ... DISABLE or, the subscription can be
160    used with the disable_on_error option. Then, you can use
161    pg_replication_origin_advance() function with the node_name (i.e.,
162    pg_16395) and the next LSN of the finish LSN (i.e., 0/14C0379). The
163    current position of origins can be seen in the
164    pg_replication_origin_status system view. Please note that skipping the
165    whole transaction includes skipping changes that might not violate any
166    constraint. This can easily make the subscriber inconsistent. The
167    additional details regarding conflicting rows, such as their origin and
168    commit timestamp can be seen in the DETAIL line of the log. But note
169    that this information is only available when track_commit_timestamp is
170    enabled on the subscriber. Users can use this information to decide
171    whether to retain the local change or adopt the remote alteration. For
172    instance, the DETAIL line in the above log indicates that the existing
173    row was modified locally. Users can manually perform a
174    remote-change-win.
175
176    When the streaming mode is parallel, the finish LSN of failed
177    transactions may not be logged. In that case, it may be necessary to
178    change the streaming mode to on or off and cause the same conflicts
179    again so the finish LSN of the failed transaction will be written to
180    the server log. For the usage of finish LSN, please refer to ALTER
181    SUBSCRIPTION ... SKIP.