]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix the missing table sync due to improper invalidation handling.
authorAmit Kapila <akapila@postgresql.org>
Thu, 25 Apr 2024 05:03:04 +0000 (10:33 +0530)
committerAmit Kapila <akapila@postgresql.org>
Thu, 25 Apr 2024 05:03:04 +0000 (10:33 +0530)
We missed performing table sync if the invalidation happened while the
non-ready tables list was being prepared. This occurs because the sync
state was set to valid at the end of non-ready table list preparation
irrespective of the invalidations processed while the list is being
prepared.

Fix it by changing the boolean variable to a tri-state enum and by setting
table state to valid only if no invalidations have occurred while the list
is being prepared.

Reprted-by: Alexander Lakhin
Diagnosed-by: Alexander Lakhin
Author: Vignesh C
Reviewed-by: Hou Zhijie, Alexander Lakhin, Ajin Cherian, Amit Kapila
Backpatch-through: 15
Discussion: https://postgr.es/m/711a6afe-edb7-1211-cc27-1bef8239eec7@gmail.com

src/backend/replication/logical/tablesync.c
src/tools/pgindent/typedefs.list

index c3dd902f8c8dbc84cefc58ab8b0f594e0b81744a..e6159acba0091b653e05c0d634c52d2545b9b779 100644 (file)
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
 
-static bool table_states_valid = false;
+typedef enum
+{
+       SYNC_TABLE_STATE_NEEDS_REBUILD,
+       SYNC_TABLE_STATE_REBUILD_STARTED,
+       SYNC_TABLE_STATE_VALID,
+} SyncingTablesState;
+
+static SyncingTablesState table_states_validity = SYNC_TABLE_STATE_NEEDS_REBUILD;
 static List *table_states_not_ready = NIL;
 static bool FetchTableStates(bool *started_tx);
 
@@ -270,7 +277,7 @@ wait_for_worker_state_change(char expected_state)
 void
 invalidate_syncing_table_states(Datum arg, int cacheid, uint32 hashvalue)
 {
-       table_states_valid = false;
+       table_states_validity = SYNC_TABLE_STATE_NEEDS_REBUILD;
 }
 
 /*
@@ -1465,13 +1472,15 @@ FetchTableStates(bool *started_tx)
 
        *started_tx = false;
 
-       if (!table_states_valid)
+       if (table_states_validity != SYNC_TABLE_STATE_VALID)
        {
                MemoryContext oldctx;
                List       *rstates;
                ListCell   *lc;
                SubscriptionRelState *rstate;
 
+               table_states_validity = SYNC_TABLE_STATE_REBUILD_STARTED;
+
                /* Clean the old lists. */
                list_free_deep(table_states_not_ready);
                table_states_not_ready = NIL;
@@ -1505,7 +1514,15 @@ FetchTableStates(bool *started_tx)
                has_subrels = (list_length(table_states_not_ready) > 0) ||
                        HasSubscriptionRelations(MySubscription->oid);
 
-               table_states_valid = true;
+               /*
+                * If the subscription relation cache has been invalidated since we
+                * entered this routine, we still use and return the relations we just
+                * finished constructing, to avoid infinite loops, but we leave the
+                * table states marked as stale so that we'll rebuild it again on next
+                * access. Otherwise, we mark the table states as valid.
+                */
+               if (table_states_validity == SYNC_TABLE_STATE_REBUILD_STARTED)
+                       table_states_validity = SYNC_TABLE_STATE_VALID;
        }
 
        return has_subrels;
index d030c485fd1b7966d769b9c19695173e648c66e2..78f3ec0cafb07c1ee471273b1b6d9d23f07f2824 100644 (file)
@@ -2635,6 +2635,7 @@ SupportRequestSelectivity
 SupportRequestSimplify
 SupportRequestWFuncMonotonic
 Syn
+SyncingTablesState
 SyncOps
 SyncRepConfigData
 SyncRepStandbyData