1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>29.7. Conflicts</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="logical-replication-gencols.html" title="29.6. Generated Column Replication" /><link rel="next" href="logical-replication-restrictions.html" title="29.8. Restrictions" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">29.7. Conflicts</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="logical-replication-gencols.html" title="29.6. Generated Column Replication">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="logical-replication.html" title="Chapter 29. Logical Replication">Up</a></td><th width="60%" align="center">Chapter 29. Logical Replication</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="logical-replication-restrictions.html" title="29.8. Restrictions">Next</a></td></tr></table><hr /></div><div class="sect1" id="LOGICAL-REPLICATION-CONFLICTS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">29.7. Conflicts <a href="#LOGICAL-REPLICATION-CONFLICTS" class="id_link">#</a></h2></div></div></div><p>
3 Logical replication behaves similarly to normal DML operations in that
4 the data will be updated even if it was changed locally on the subscriber
5 node. If incoming data violates any constraints the replication will
6 stop. This is referred to as a <em class="firstterm">conflict</em>. When
7 replicating <code class="command">UPDATE</code> or <code class="command">DELETE</code>
8 operations, missing data is also considered as a
9 <em class="firstterm">conflict</em>, but does not result in an error and such
10 operations will simply be skipped.
12 Additional logging is triggered, and the conflict statistics are collected (displayed in the
13 <a class="link" href="monitoring-stats.html#MONITORING-PG-STAT-SUBSCRIPTION-STATS" title="27.2.9. pg_stat_subscription_stats"><code class="structname">pg_stat_subscription_stats</code></a> view)
14 in the following <em class="firstterm">conflict</em> cases:
15 </p><div class="variablelist"><dl class="variablelist"><dt id="CONFLICT-INSERT-EXISTS"><span class="term"><code class="literal">insert_exists</code></span> <a href="#CONFLICT-INSERT-EXISTS" class="id_link">#</a></dt><dd><p>
16 Inserting a row that violates a <code class="literal">NOT DEFERRABLE</code>
17 unique constraint. Note that to log the origin and commit
18 timestamp details of the conflicting key,
19 <a class="link" href="runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP"><code class="varname">track_commit_timestamp</code></a>
20 should be enabled on the subscriber. In this case, an error will be
21 raised until the conflict is resolved manually.
22 </p></dd><dt id="CONFLICT-UPDATE-ORIGIN-DIFFERS"><span class="term"><code class="literal">update_origin_differs</code></span> <a href="#CONFLICT-UPDATE-ORIGIN-DIFFERS" class="id_link">#</a></dt><dd><p>
23 Updating a row that was previously modified by another origin.
24 Note that this conflict can only be detected when
25 <a class="link" href="runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP"><code class="varname">track_commit_timestamp</code></a>
26 is enabled on the subscriber. Currently, the update is always applied
27 regardless of the origin of the local row.
28 </p></dd><dt id="CONFLICT-UPDATE-EXISTS"><span class="term"><code class="literal">update_exists</code></span> <a href="#CONFLICT-UPDATE-EXISTS" class="id_link">#</a></dt><dd><p>
29 The updated value of a row violates a <code class="literal">NOT DEFERRABLE</code>
30 unique constraint. Note that to log the origin and commit
31 timestamp details of the conflicting key,
32 <a class="link" href="runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP"><code class="varname">track_commit_timestamp</code></a>
33 should be enabled on the subscriber. In this case, an error will be
34 raised until the conflict is resolved manually. Note that when updating a
35 partitioned table, if the updated row value satisfies another partition
36 constraint resulting in the row being inserted into a new partition, the
37 <code class="literal">insert_exists</code> conflict may arise if the new row
38 violates a <code class="literal">NOT DEFERRABLE</code> unique constraint.
39 </p></dd><dt id="CONFLICT-UPDATE-MISSING"><span class="term"><code class="literal">update_missing</code></span> <a href="#CONFLICT-UPDATE-MISSING" class="id_link">#</a></dt><dd><p>
40 The row to be updated was not found. The update will simply be
41 skipped in this scenario.
42 </p></dd><dt id="CONFLICT-DELETE-ORIGIN-DIFFERS"><span class="term"><code class="literal">delete_origin_differs</code></span> <a href="#CONFLICT-DELETE-ORIGIN-DIFFERS" class="id_link">#</a></dt><dd><p>
43 Deleting a row that was previously modified by another origin. Note that
44 this conflict can only be detected when
45 <a class="link" href="runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP"><code class="varname">track_commit_timestamp</code></a>
46 is enabled on the subscriber. Currently, the delete is always applied
47 regardless of the origin of the local row.
48 </p></dd><dt id="CONFLICT-DELETE-MISSING"><span class="term"><code class="literal">delete_missing</code></span> <a href="#CONFLICT-DELETE-MISSING" class="id_link">#</a></dt><dd><p>
49 The row to be deleted was not found. The delete will simply be
50 skipped in this scenario.
51 </p></dd><dt id="CONFLICT-MULTIPLE-UNIQUE-CONFLICTS"><span class="term"><code class="literal">multiple_unique_conflicts</code></span> <a href="#CONFLICT-MULTIPLE-UNIQUE-CONFLICTS" class="id_link">#</a></dt><dd><p>
52 Inserting or updating a row violates multiple
53 <code class="literal">NOT DEFERRABLE</code> unique constraints. Note that to log
54 the origin and commit timestamp details of conflicting keys, ensure
55 that <a class="link" href="runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP"><code class="varname">track_commit_timestamp</code></a>
56 is enabled on the subscriber. In this case, an error will be raised until
57 the conflict is resolved manually.
58 </p></dd></dl></div><p>
59 Note that there are other conflict scenarios, such as exclusion constraint
60 violations. Currently, we do not provide additional details for them in the
63 The log format for logical replication conflicts is as follows:
64 </p><pre class="synopsis">
65 LOG: conflict detected on relation "<em class="replaceable"><code>schemaname</code></em>.<em class="replaceable"><code>tablename</code></em>": conflict=<em class="replaceable"><code>conflict_type</code></em>
66 DETAIL: <em class="replaceable"><code>detailed_explanation</code></em>.
67 {<em class="replaceable"><code>detail_values</code></em> [; ... ]}.
69 <span class="phrase">where <em class="replaceable"><code>detail_values</code></em> is one of:</span>
71 <code class="literal">Key</code> (<em class="replaceable"><code>column_name</code></em> [<span class="optional">, ...</span>])=(<em class="replaceable"><code>column_value</code></em> [<span class="optional">, ...</span>])
72 <code class="literal">existing local row</code> [<span class="optional">(<em class="replaceable"><code>column_name</code></em> [<span class="optional">, ...</span>])=</span>](<em class="replaceable"><code>column_value</code></em> [<span class="optional">, ...</span>])
73 <code class="literal">remote row</code> [<span class="optional">(<em class="replaceable"><code>column_name</code></em> [<span class="optional">, ...</span>])=</span>](<em class="replaceable"><code>column_value</code></em> [<span class="optional">, ...</span>])
74 <code class="literal">replica identity</code> {(<em class="replaceable"><code>column_name</code></em> [<span class="optional">, ...</span>])=(<em class="replaceable"><code>column_value</code></em> [<span class="optional">, ...</span>]) | full [<span class="optional">(<em class="replaceable"><code>column_name</code></em> [<span class="optional">, ...</span>])=</span>](<em class="replaceable"><code>column_value</code></em> [<span class="optional">, ...</span>])}
77 The log provides the following information:
78 </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">LOG</code></span></dt><dd><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
79 <em class="replaceable"><code>schemaname</code></em>.<em class="replaceable"><code>tablename</code></em>
80 identifies the local relation involved in the conflict.
81 </p></li><li class="listitem"><p>
82 <em class="replaceable"><code>conflict_type</code></em> is the type of conflict that occurred
83 (e.g., <code class="literal">insert_exists</code>, <code class="literal">update_exists</code>).
84 </p></li></ul></div></dd><dt><span class="term"><code class="literal">DETAIL</code></span></dt><dd><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
85 <em class="replaceable"><code>detailed_explanation</code></em> includes
86 the origin, transaction ID, and commit timestamp of the transaction that
87 modified the existing local row, if available.
88 </p></li><li class="listitem"><p>
89 The <code class="literal">Key</code> section includes the key values of the local
90 row that violated a unique constraint for
91 <code class="literal">insert_exists</code>, <code class="literal">update_exists</code> or
92 <code class="literal">multiple_unique_conflicts</code> conflicts.
93 </p></li><li class="listitem"><p>
94 The <code class="literal">existing local row</code> section includes the local
95 row if its origin differs from the remote row for
96 <code class="literal">update_origin_differs</code> or <code class="literal">delete_origin_differs</code>
97 conflicts, or if the key value conflicts with the remote row for
98 <code class="literal">insert_exists</code>, <code class="literal">update_exists</code> or
99 <code class="literal">multiple_unique_conflicts</code> conflicts.
100 </p></li><li class="listitem"><p>
101 The <code class="literal">remote row</code> section includes the new row from
102 the remote insert or update operation that caused the conflict. Note that
103 for an update operation, the column value of the new row will be null
104 if the value is unchanged and toasted.
105 </p></li><li class="listitem"><p>
106 The <code class="literal">replica identity</code> section includes the replica
107 identity key values that were used to search for the existing local
108 row to be updated or deleted. This may include the full row value
109 if the local relation is marked with
110 <a class="link" href="sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY-FULL"><code class="literal">REPLICA IDENTITY FULL</code></a>.
111 </p></li><li class="listitem"><p>
112 <em class="replaceable"><code>column_name</code></em> is the column name.
113 For <code class="literal">existing local row</code>, <code class="literal">remote row</code>,
114 and <code class="literal">replica identity full</code> cases, column names are
115 logged only if the user lacks the privilege to access all columns of
116 the table. If column names are present, they appear in the same order
117 as the corresponding column values.
118 </p></li><li class="listitem"><p>
119 <em class="replaceable"><code>column_value</code></em> is the column value.
120 The large column values are truncated to 64 bytes.
121 </p></li><li class="listitem"><p>
122 Note that in case of <code class="literal">multiple_unique_conflicts</code> conflict,
123 multiple <em class="replaceable"><code>detailed_explanation</code></em>
124 and <em class="replaceable"><code>detail_values</code></em> lines
125 will be generated, each detailing the conflict information associated
128 </p></li></ul></div></dd></dl></div><p>
130 Logical replication operations are performed with the privileges of the role
131 which owns the subscription. Permissions failures on target tables will
132 cause replication conflicts, as will enabled
133 <a class="link" href="ddl-rowsecurity.html" title="5.9. Row Security Policies">row-level security</a> on target tables
134 that the subscription owner is subject to, without regard to whether any
135 policy would ordinarily reject the <code class="command">INSERT</code>,
136 <code class="command">UPDATE</code>, <code class="command">DELETE</code> or
137 <code class="command">TRUNCATE</code> which is being replicated. This restriction on
138 row-level security may be lifted in a future version of
139 <span class="productname">PostgreSQL</span>.
141 A conflict that produces an error will stop the replication; it must be
142 resolved manually by the user. Details about the conflict can be found in
143 the subscriber's server log.
145 The resolution can be done either by changing data or permissions on the subscriber so
146 that it does not conflict with the incoming change or by skipping the
147 transaction that conflicts with the existing data. When a conflict produces
148 an error, the replication won't proceed, and the logical replication worker will
149 emit the following kind of message to the subscriber's server log:
150 </p><pre class="screen">
151 ERROR: conflict detected on relation "public.test": conflict=insert_exists
152 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.
153 Key (c)=(1); existing local row (1, 'local'); remote row (1, 'remote').
154 CONTEXT: processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 0/14C0378
156 The LSN of the transaction that contains the change violating the constraint and
157 the replication origin name can be found from the server log (LSN 0/14C0378 and
158 replication origin <code class="literal">pg_16395</code> in the above case). The
159 transaction that produced the conflict can be skipped by using
160 <a class="link" href="sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-SKIP"><code class="command">ALTER SUBSCRIPTION ... SKIP</code></a>
162 (i.e., LSN 0/14C0378). The finish LSN could be an LSN at which the transaction
163 is committed or prepared on the publisher. Alternatively, the transaction can
164 also be skipped by calling the <a class="link" href="functions-admin.html#PG-REPLICATION-ORIGIN-ADVANCE">
165 <code class="function">pg_replication_origin_advance()</code></a> function.
166 Before using this function, the subscription needs to be disabled temporarily
167 either by <a class="link" href="sql-altersubscription.html#SQL-ALTERSUBSCRIPTION-PARAMS-DISABLE">
168 <code class="command">ALTER SUBSCRIPTION ... DISABLE</code></a> or, the
169 subscription can be used with the
170 <a class="link" href="sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-DISABLE-ON-ERROR"><code class="literal">disable_on_error</code></a>
171 option. Then, you can use <code class="function">pg_replication_origin_advance()</code>
172 function with the <em class="parameter"><code>node_name</code></em> (i.e., <code class="literal">pg_16395</code>)
173 and the next LSN of the finish LSN (i.e., 0/14C0379). The current position of
174 origins can be seen in the <a class="link" href="view-pg-replication-origin-status.html" title="53.19. pg_replication_origin_status">
175 <code class="structname">pg_replication_origin_status</code></a> system view.
176 Please note that skipping the whole transaction includes skipping changes that
177 might not violate any constraint. This can easily make the subscriber
179 The additional details regarding conflicting rows, such as their origin and
180 commit timestamp can be seen in the <code class="literal">DETAIL</code> line of the
181 log. But note that this information is only available when
182 <a class="link" href="runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP"><code class="varname">track_commit_timestamp</code></a>
183 is enabled on the subscriber. Users can use this information to decide
184 whether to retain the local change or adopt the remote alteration. For
185 instance, the <code class="literal">DETAIL</code> line in the above log indicates that
186 the existing row was modified locally. Users can manually perform a
190 <a class="link" href="sql-createsubscription.html#SQL-CREATESUBSCRIPTION-PARAMS-WITH-STREAMING"><code class="literal">streaming</code></a>
191 mode is <code class="literal">parallel</code>, the finish LSN of failed transactions
192 may not be logged. In that case, it may be necessary to change the streaming
193 mode to <code class="literal">on</code> or <code class="literal">off</code> and cause the same
194 conflicts again so the finish LSN of the failed transaction will be written
195 to the server log. For the usage of finish LSN, please refer to <a class="link" href="sql-altersubscription.html" title="ALTER SUBSCRIPTION"><code class="command">ALTER SUBSCRIPTION ...
197 </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="logical-replication-gencols.html" title="29.6. Generated Column Replication">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="logical-replication.html" title="Chapter 29. Logical Replication">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="logical-replication-restrictions.html" title="29.8. Restrictions">Next</a></td></tr><tr><td width="40%" align="left" valign="top">29.6. Generated Column Replication </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 29.8. Restrictions</td></tr></table></div></body></html>