Fix the missing table sync due to improper invalidation handling.

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
This commit is contained in:
Amit Kapila 2024-04-25 10:52:34 +05:30
parent cd0678a9bb
commit a9155efc70
2 changed files with 22 additions and 4 deletions

View File

@ -122,7 +122,14 @@
#include "utils/syscache.h"
#include "utils/usercontext.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);
@ -272,7 +279,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;
}
/*
@ -1556,13 +1563,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;
@ -1596,7 +1605,15 @@ FetchTableStates(bool *started_tx)
has_subrels = (table_states_not_ready != NIL) ||
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;

View File

@ -2676,6 +2676,7 @@ SupportRequestSelectivity
SupportRequestSimplify
SupportRequestWFuncMonotonic
Syn
SyncingTablesState
SyncOps
SyncRepConfigData
SyncRepStandbyData