Improve log messages and docs for slot synchronization. master github/master
authorAmit Kapila
Thu, 19 Jun 2025 04:18:08 +0000 (09:48 +0530)
committerAmit Kapila
Thu, 19 Jun 2025 04:18:08 +0000 (09:48 +0530)
Improve the clarity of LOG messages when a failover logical slot
synchronization fails, making the reasons more explicit for easier
debugging.

Update the documentation to outline scenarios where slot synchronization
can fail, especially during the initial sync, and emphasize that
pg_sync_replication_slot() is primarily intended for testing and
debugging purposes.

We also discussed improving the functionality of
pg_sync_replication_slot() so that it can be used reliably, but we would
take up that work for next version after some more discussion and review.

Reported-by: Suraj Kharage
Author: shveta malik 
Reviewed-by: Zhijie Hou
Reviewed-by: Peter Smith
Reviewed-by: Amit Kapila
Backpatch-through: 17, where it was introduced
Discussion: https://postgr.es/m/CAF1DzPWTcg+m+x+oVVB=y4q9=PYYsL_mujVp7uJr-_oUtWNGbA@mail.gmail.com

doc/src/sgml/func.sgml
doc/src/sgml/logicaldecoding.sgml
src/backend/replication/logical/slotsync.c

index c67688cbf5f98fbcb6b87a91d05bc27d2ab007ca..8d7d9a2f3e8e88a06b83864c22b1ac121f05ab21 100644 (file)
@@ -29698,7 +29698,7 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
       
 
       
-       
+       id="pg-logical-slot-get-binary-changes" role="func_table_entry">
         
          pg_logical_slot_get_binary_changes
         
@@ -29970,7 +29970,9 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
         standby server. Temporary synced slots, if any, cannot be used for
         logical decoding and must be dropped after promotion. See
          for details.
-        Note that this function cannot be executed if
+        Note that this function is primarily intended for testing and
+        debugging purposes and should be used with caution. Additionaly,
+        this function cannot be executed if
         
         sync_replication_slots is enabled and the slotsync
         worker is already running to perform the synchronization of slots.
index dd9e83b08eaf10b367bfc330145a5fe3d602ea8d..5c5957e0d37a146088e0e3ab8b9cfde8907deb24 100644 (file)
@@ -370,10 +370,10 @@ postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NU
      pg_create_logical_replication_slot, or by
      using the 
      failover option of
-     CREATE SUBSCRIPTION during slot creation, and then calling
-     -sync-replication-slots">
-     <function>pg_sync_replication_slots
-     on the standby. By setting 
+     CREATE SUBSCRIPTION during slot creation.
+     Additionally, enabling -sync-replication-slots">
+     <varname>sync_replication_slots on the standby
+     is required. By enabling 
      sync_replication_slots
      on the standby, the failover slots can be synchronized periodically in
      the slotsync worker. For the synchronization to work, it is mandatory to
@@ -398,6 +398,52 @@ postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NU
      receiving the WAL up to the latest flushed position on the primary server.
     
 
+    
+     
+      While enabling 
+      sync_replication_slots allows for automatic
+      periodic synchronization of failover slots, they can also be manually
+      synchronized using the 
+      pg_sync_replication_slots function on the standby.
+      However, this function is primarily intended for testing and debugging and
+      should be used with caution. Unlike automatic synchronization, it does not
+      include cyclic retries, making it more prone to synchronization failures,
+      particularly during initial sync scenarios where the required WAL files
+      or catalog rows for the slot may have already been removed or are at risk
+      of being removed on the standby. In contrast, automatic synchronization
+      via sync_replication_slots provides continuous slot
+      updates, enabling seamless failover and supporting high availability.
+      Therefore, it is the recommended method for synchronizing slots.
+     
+    
+
+    
+     When slot synchronization is configured as recommended,
+     and the initial synchronization is performed either automatically or
+     manually via pg_sync_replication_slot, the standby can persist the
+     synchronized slot only if the following condition is met: The logical
+     replication slot on the primary must retain WALs and system catalog
+     rows that are still available on the standby. This ensures data
+     integrity and allows logical replication to continue smoothly after
+     promotion.
+     If the required WALs or catalog rows have already been purged from the
+     standby, the slot will not be persisted to avoid data loss. In such
+     cases, the following log message may appear:
+
+     LOG:  could not synchronize replication slot "failover_slot"
+     DETAIL:  Synchronization could lead to data loss as the remote slot needs WAL at LSN 0/3003F28 and catalog xmin 754, but the standby has LSN 0/3003F28 and catalog xmin 756
+
+     If the logical replication slot is actively used by a consumer, no
+     manual intervention is needed; the slot will advance automatically,
+     and synchronization will resume in the next cycle. However, if no
+     consumer is configured, it is advisable to manually advance the slot
+     on the primary using 
+     pg_logical_slot_get_changes or
+     
+     pg_logical_slot_get_binary_changes,
+     allowing synchronization to proceed.
+    
+
     
      The ability to resume logical replication after failover depends upon the
      pg_replication_slots.synced
index 656e66e0ae0a10888da111b22835bfdd471f5d42..f1dcbebfa1ae7f6f07645feb86db735f63cb0c3d 100644 (file)
@@ -211,9 +211,9 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid,
         * impact the users, so we used DEBUG1 level to log the message.
         */
        ereport(slot->data.persistency == RS_TEMPORARY ? LOG : DEBUG1,
-               errmsg("could not synchronize replication slot \"%s\" because remote slot precedes local slot",
+               errmsg("could not synchronize replication slot \"%s\"",
                       remote_slot->name),
-               errdetail("The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u.",
+               errdetail("Synchronization could lead to data loss as the remote slot needs WAL at LSN %X/%X and catalog xmin %u, but the standby has LSN %X/%X and catalog xmin %u.",
                          LSN_FORMAT_ARGS(remote_slot->restart_lsn),
                          remote_slot->catalog_xmin,
                          LSN_FORMAT_ARGS(slot->data.restart_lsn),
@@ -593,7 +593,7 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid)
    {
        ereport(LOG,
                errmsg("could not synchronize replication slot \"%s\"", remote_slot->name),
-               errdetail("Logical decoding could not find consistent point from local slot's LSN %X/%X.",
+               errdetail("Synchronization could lead to data loss as standby could not build a consistent snapshot to decode WALs at LSN %X/%X.",
                          LSN_FORMAT_ARGS(slot->data.restart_lsn)));
 
        return false;