From 9d6b065a25c50211b29d5e26d5f83670200bae65 Mon Sep 17 00:00:00 2001 From: "jhonathan.cruz" Date: Sun, 14 Dec 2025 13:13:36 -0300 Subject: [PATCH] docs: add logical replication examples and clarify autovacuum and XID freezing behavior --- doc/src/sgml/logical-replication.sgml | 71 +++++++++++++++++++++++++++ doc/src/sgml/maintenance.sgml | 56 +++++++++++++++++++++ doc/src/sgml/mvcc.sgml | 49 ++++++++++++++++++ 3 files changed, 176 insertions(+) diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml index aa013f348d4..87ac151ec88 100644 --- a/doc/src/sgml/logical-replication.sgml +++ b/doc/src/sgml/logical-replication.sgml @@ -3543,4 +3543,75 @@ CREATE SUBSCRIPTION mysub CONNECTION 'dbname=foo host=bar user=repuser' PUBLICAT incremental changes to those tables. +
+ Practical Usage Examples + + + While logical replication is conceptually simple, many users struggle with + initial configuration because real-world examples are spread across + different sections. This part consolidates common usage patterns with + complete and reproducible examples. + + + + Single-Table Replication Example + + + The following example demonstrates a minimal setup where a single table + is replicated from publisher to subscriber. This is a common use case for + operational reporting and incremental data ingestion by downstream + systems. + + + +-- On the publisher: +CREATE TABLE public.sales_events ( + id bigserial PRIMARY KEY, + event_time timestamptz NOT NULL, + payload jsonb NOT NULL +); + +ALTER TABLE public.sales_events REPLICA IDENTITY FULL; + +CREATE PUBLICATION sales_pub FOR TABLE public.sales_events; + +-- On the subscriber: +CREATE SUBSCRIPTION sales_sub + CONNECTION 'host=publisher port=5432 dbname=app user=replicator' + PUBLICATION sales_pub; + + + + After the subscription is created, PostgreSQL performs an initial table + copy. Users often assume this happens in the background, but it actually + uses a separate apply worker. Monitoring can be done via + + pg_stat_subscription + . + + + + + Clarification of Initial Synchronization Behavior + + Initial synchronization is commonly misunderstood. Each table is copied in + a dedicated worker process, which can lead to higher-than-expected + resource usage on large schemas. Administrators may prefer to temporarily + disable table copy and load the initial data manually. This can be done + using copy_data = false during subscription creation. + + + + + Conflict Resolution in Apply Workers + + Conflicts occur when the subscriber contains preexisting data or when + concurrent writes race with replicated changes. PostgreSQL always + prioritizes local transactions, causing replicated transactions to abort + and retry. This behavior is rarely documented clearly, yet it is + essential for users handling high write volumes. + + + +
diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 08e6489afb8..7a0a83a0154 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1232,4 +1232,60 @@ pg_ctl start | rotatelogs /var/log/pgsql_log 86400 files, as well as detection of many other extraordinary conditions. +
+ Understanding Autovacuum Behavior in Depth + + + The autovacuum launcher dynamically decides when to create worker processes + based on table activity. Although this mechanism operates automatically, it + is sensitive to workload patterns, visibility map state, freeze thresholds, + and cost-based throttling. This section clarifies these behaviors to help + administrators diagnose performance regressions and long-running + autovacuum cycles. + + + + Cost-Based Throttling + + + Autovacuum workers obey cost-based throttling rules that were originally + designed for manual VACUUM operations. When the accumulated cost exceeds + autovacuum_vacuum_cost_limit, the worker sleeps for the + duration defined by autovacuum_vacuum_cost_delay. In + environments with high write throughput, throttling can cause autovacuum + to take significantly longer than expected. + + + + A common misconception is that increasing the number of autovacuum + workers solves slow autovacuum cycles. In practice, cost-based throttling + often becomes the bottleneck. In such cases, adjusting cost_limit upward, + or disabling throttling entirely for specific relations, may be more + effective. + + + + + Diagnosing Long-Running Autovacuum Operations + + + Administrators frequently observe autovacuum workers running for hours on + tables with large dead tuples or bloated indexes. The primary causes are: + + + + Heavy write activity preventing visibility map advancement. + Cost-based throttling limiting processing rate. + Background worker slots exhausted by other processes. + Insufficient I/O bandwidth for vacuuming operations. + + + + Monitoring can be performed using + . If index scans dominate + runtime, administrators should consider index deduplication, partitioning, + or targeted VACUUM (INDEX_CLEANUP OFF). + + +
diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index 049ee75a4ba..317cdd723b8 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -1944,4 +1944,53 @@ SELECT pg_advisory_lock(q.id) FROM indexes should be used instead. +
+ Understanding Transaction Freezing and Anti-Wraparound Protection + + + PostgreSQL must frequently freeze old tuples to prevent transaction ID + wraparound, which would otherwise cause catalog corruption and data loss. + Although this mechanism is documented, many details are not fully clear to + new users. This section explains the practical impact of freezing, + thresholds, and autovacuum interaction. + + + + Freeze Thresholds and Vacuum Triggering + + + Autovacuum triggers a freeze operation when a relation reaches the + threshold defined by autovacuum_freeze_max_age. In + addition, each table carries its own age counter at the page level, based + on the oldest XID present. When this counter crosses + vacuum_freeze_min_age, tuples are marked as frozen. + + + + A common misunderstanding is that freezing is expensive. In reality, + freezing is often cheaper than regular vacuuming, because frozen tuples + no longer require XID visibility checks. High freeze ages only become a + problem when autovacuum is unable to keep up, typically due to sustained + heavy writes or throttling constraints. + + + + + Visibility Map and Freeze Operations + + + Freezing interacts closely with the visibility map. When all tuples in a + page are frozen or visible to all transactions, the page can be marked as + all-visible. This reduces scanning overhead for future vacuum operations. + However, frequent updates prevent visibility map bits from being set, + increasing vacuum and freeze pressure. + + + + Administrators should monitor visibility map saturation via + pgstattuple or external tooling to detect tables that + are chronically difficult to vacuum. + + +
-- 2.45.1.windows.1