]> git.ipfire.org Git - thirdparty/postgresql.git/commit
Allow logical replication conflicts to be logged to a table.
authorAmit Kapila <akapila@postgresql.org>
Thu, 2 Jul 2026 02:14:27 +0000 (07:44 +0530)
committerAmit Kapila <akapila@postgresql.org>
Thu, 2 Jul 2026 02:56:07 +0000 (08:26 +0530)
commita5918fddf10d297c70f7ec9067e9177e0be6d520
tree0539e74eb9363b209f7eb25a880c2c325c3fd46c
parent3b066de6c0a1dadbd8bed107e55cae659af0598f
Allow logical replication conflicts to be logged to a table.

Until now, logical replication conflicts were only written as plain text
to the server log, which is hard to query, analyze, or feed into external
monitoring and automation.

This commit adds a conflict_log_destination option to CREATE SUBSCRIPTION
and ALTER SUBSCRIPTION that controls where conflicts are recorded. It
accepts 'log' (the existing behavior), 'table', or 'all'.

When table logging is enabled ('table' or 'all'), an internal log table
named pg_conflict_log_<subid> is created automatically in a dedicated,
system-managed pg_conflict namespace. Using a separate namespace avoids
collisions with user table names and lets the table be shielded from
direct modification. The table is tied to the subscription through an
internal dependency, so it is dropped automatically when the subscription
is removed.

The conflict details, including the local and remote tuples, are stored in
JSON columns, so a single table layout can accommodate rows from tables
with different schemas. The table also records the local and remote
transaction IDs, LSNs, commit timestamps, and the conflict type, providing
a complete record for post-mortem analysis.

A per-subscription table was chosen over a single global log because it
aligns table ownership with the subscription lifecycle. This keeps
permission management simple: the subscription owner can perform the
permitted maintenance operations without the security concerns or
Row-Level Security that a shared table would require.

Because the table is system-managed, it is protected from direct
manipulation: DDL (such as ALTER, DROP, CREATE INDEX, and adding a
trigger, rule, policy, or extended statistics), use as an inheritance
parent or a foreign-key target, and manual INSERT, UPDATE, MERGE, or row
locking are all rejected.  Only DELETE and TRUNCATE are permitted, so that
users can prune old conflict rows.

Conflict log tables are also excluded from publications, even those
defined with FOR ALL TABLES or FOR TABLES IN SCHEMA.

This commit only establishes the conflict log table along with its
creation, cleanup, and protection; recording the conflicts detected
during apply into the table will be handled in a follow-up commit.

Author: Dilip Kumar <dilipbalaut@gmail.com>
Author: Nisha Moond <nisha.moond412@gmail.com>
Author: Amit Kapila <akapila@postgresql.org>
Reviewed-by: Shveta Malik <shveta.malik@gmail.com>
Reviewed-by: Vignesh C <vignesh21@gmail.com>
Reviewed-by: Peter Smith <smithpb2250@gmail.com>
Reviewed-by: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/CAFiTN-u5D5o_AGNbHRZHaOqAMWkxLf%2BhSk_r9X3gv6HbLOB5%2Bg%40mail.gmail.com
31 files changed:
doc/src/sgml/ddl.sgml
doc/src/sgml/glossary.sgml
doc/src/sgml/logical-replication.sgml
doc/src/sgml/ref/alter_subscription.sgml
doc/src/sgml/ref/create_subscription.sgml
doc/src/sgml/ref/drop_subscription.sgml
src/backend/catalog/aclchk.c
src/backend/catalog/catalog.c
src/backend/catalog/pg_publication.c
src/backend/catalog/pg_subscription.c
src/backend/catalog/system_views.sql
src/backend/commands/lockcmds.c
src/backend/commands/policy.c
src/backend/commands/statscmds.c
src/backend/commands/subscriptioncmds.c
src/backend/commands/tablecmds.c
src/backend/commands/trigger.c
src/backend/executor/execMain.c
src/backend/replication/logical/conflict.c
src/backend/rewrite/rewriteDefine.c
src/bin/initdb/initdb.c
src/bin/psql/tab-complete.in.c
src/include/catalog/catalog.h
src/include/catalog/catversion.h
src/include/catalog/pg_namespace.dat
src/include/catalog/pg_subscription.h
src/include/replication/conflict.h
src/test/regress/expected/subscription.out
src/test/regress/sql/subscription.sql
src/test/subscription/t/035_conflicts.pl
src/tools/pgindent/typedefs.list