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 <[email protected]>
Author: Nisha Moond <[email protected]>
Author: Amit Kapila <[email protected]>
Reviewed-by: Shveta Malik <[email protected]>
Reviewed-by: Vignesh C <[email protected]>
Reviewed-by: Peter Smith <[email protected]>
Reviewed-by: Shlok Kyal <[email protected]>
Reviewed-by: Masahiko Sawada <[email protected]>
Discussion: 
https://postgr.es/m/CAFiTN-u5D5o_AGNbHRZHaOqAMWkxLf%2BhSk_r9X3gv6HbLOB5%2Bg%40mail.gmail.com

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/a5918fddf10d297c70f7ec9067e9177e0be6d520

Modified Files
--------------
doc/src/sgml/ddl.sgml                      |  20 ++
doc/src/sgml/glossary.sgml                 |  12 ++
doc/src/sgml/logical-replication.sgml      |  15 ++
doc/src/sgml/ref/alter_subscription.sgml   |  12 +-
doc/src/sgml/ref/create_subscription.sgml  |  49 +++++
doc/src/sgml/ref/drop_subscription.sgml    |   8 +
src/backend/catalog/aclchk.c               |  58 ++++--
src/backend/catalog/catalog.c              |  29 ++-
src/backend/catalog/pg_publication.c       |  14 +-
src/backend/catalog/pg_subscription.c      |   7 +
src/backend/catalog/system_views.sql       |   4 +-
src/backend/commands/lockcmds.c            |  24 ++-
src/backend/commands/policy.c              |  12 ++
src/backend/commands/statscmds.c           |  14 ++
src/backend/commands/subscriptioncmds.c    | 214 ++++++++++++++++++++-
src/backend/commands/tablecmds.c           |  95 +++++++++-
src/backend/commands/trigger.c             |  25 +++
src/backend/executor/execMain.c            |  28 +++
src/backend/replication/logical/conflict.c | 172 +++++++++++++++++
src/backend/rewrite/rewriteDefine.c        |  24 +++
src/bin/initdb/initdb.c                    |   6 +
src/bin/psql/tab-complete.in.c             |   8 +-
src/include/catalog/catalog.h              |   2 +
src/include/catalog/catversion.h           |   2 +-
src/include/catalog/pg_namespace.dat       |   3 +
src/include/catalog/pg_subscription.h      |  10 +
src/include/replication/conflict.h         |  26 +++
src/test/regress/expected/subscription.out | 295 +++++++++++++++++++++++++++++
src/test/regress/sql/subscription.sql      | 234 +++++++++++++++++++++++
src/test/subscription/t/035_conflicts.pl   |  67 ++++++-
src/tools/pgindent/typedefs.list           |   2 +
31 files changed, 1451 insertions(+), 40 deletions(-)

Reply via email to