diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index acf6494cd6..e621eb5e44 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -32,7 +32,12 @@ * transaction commit is received and also wait for the worker to finish at * commit. This preserves commit ordering and avoids writing to and reading * from file in most cases. We still need to spill if there is no worker - * available. + * available. It is important to maintain commit order to avoid failures + * due to (a) transaction dependencies, say if we insert a row in the first + * transaction and update it in the second transaction then allowing to apply + * both in parallel can lead to failure in the update. (b) deadlocks, allowing + * transactions that update the same set of rows/tables in opposite order to be + * applied in parallel can lead to deadlocks. * * 2) Write to temporary files and apply when the final commit arrives * @@ -1366,14 +1371,12 @@ apply_handle_stream_stop(StringInfo s) char action = LOGICAL_REP_MSG_STREAM_STOP; /* - * There is no need to wait here to allow stream_stop to complete by - * background worker to avoid deadlocks. - * - * The deadlock problem only occurs if relation's unique - * index/constraint is different between publisher and subscriber. But - * in these cases, we do not allow to apply streamed transaction in the - * apply background worker (see function - * apply_bgworker_relation_check). + * Unlike stream_commit, we don't need to wait here for stream_stop to + * finish. Allowing the other transaction to be applied before stream_stop + * is finished can only lead to failures if the unique index/constraint is + * different between publisher and subscriber. But for such cases, we don't + * allow streamed transactions to be applied in parallel. See + * apply_bgworker_relation_check. */ apply_bgworker_send_data(stream_apply_worker, 1, &action); @@ -2764,7 +2767,11 @@ apply_handle_stream_commit(StringInfo s) /* Send commit message */ apply_bgworker_send_data(wstate, s->len, s->data); - /* Wait for apply background worker to finish */ + /* + * Wait for apply background worker to finish. This is required to + * maintain commit order which avoids failures due to transaction + * dependencies and deadlocks. + */ apply_bgworker_wait_for(wstate, APPLY_BGWORKER_FINISHED); pgstat_report_stat(false);