aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/transam/xlog.c25
-rw-r--r--src/backend/storage/ipc/sinvaladt.c41
-rw-r--r--src/include/storage/sinvaladt.h1
3 files changed, 67 insertions, 0 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7654ad76de1..f1a795bba9f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -70,6 +70,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/reinit.h"
+#include "storage/sinvaladt.h"
#include "storage/smgr.h"
#include "storage/spin.h"
#include "storage/sync.h"
@@ -8020,6 +8021,30 @@ StartupXLOG(void)
}
/*
+ * Invalidate all sinval-managed caches before READ WRITE transactions
+ * begin. The xl_heap_inplace WAL record doesn't store sufficient data
+ * for invalidations. The commit record, if any, has the invalidations.
+ * However, the inplace update is permanent, whether or not we reach a
+ * commit record. Fortunately, read-only transactions tolerate caches not
+ * reflecting the latest inplace updates. Read-only transactions
+ * experience the notable inplace updates as follows:
+ *
+ * - relhasindex=true affects readers only after the CREATE INDEX
+ * transaction commit makes an index fully available to them.
+ *
+ * - datconnlimit=DATCONNLIMIT_INVALID_DB affects readers only at
+ * InitPostgres() time, and that read does not use a cache.
+ *
+ * - relfrozenxid, datfrozenxid, relminmxid, and datminmxid have no effect
+ * on readers.
+ *
+ * Hence, hot standby queries (all READ ONLY) function correctly without
+ * the missing invalidations. This avoided changing the WAL format in
+ * back branches.
+ */
+ SIResetAll();
+
+ /*
* Preallocate additional log files, if wanted.
*/
PreallocXlogFiles(EndOfLog);
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index 946bd8e3cb5..f0e2fb96ea3 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -748,6 +748,47 @@ SICleanupQueue(bool callerHasWriteLock, int minFree)
}
}
+/*
+ * SIResetAll
+ * Mark all active backends as "reset"
+ *
+ * Use this when we don't know what needs to be invalidated. It's a
+ * cluster-wide InvalidateSystemCaches(). This was a back-branch-only remedy
+ * to avoid a WAL format change.
+ *
+ * The implementation is like SICleanupQueue(false, MAXNUMMESSAGES + 1), with
+ * one addition. SICleanupQueue() assumes minFree << MAXNUMMESSAGES, so it
+ * assumes hasMessages==true for any backend it resets. We're resetting even
+ * fully-caught-up backends, so we set hasMessages.
+ */
+void
+SIResetAll(void)
+{
+ SISeg *segP = shmInvalBuffer;
+ int i;
+
+ LWLockAcquire(SInvalWriteLock, LW_EXCLUSIVE);
+ LWLockAcquire(SInvalReadLock, LW_EXCLUSIVE);
+
+ for (i = 0; i < segP->lastBackend; i++)
+ {
+ ProcState *stateP = &segP->procState[i];
+
+ if (stateP->procPid == 0 || stateP->sendOnly)
+ continue;
+
+ /* Consuming the reset will update "nextMsgNum" and "signaled". */
+ stateP->resetState = true;
+ stateP->hasMessages = true;
+ }
+
+ segP->minMsgNum = segP->maxMsgNum;
+ segP->nextThreshold = CLEANUP_MIN;
+
+ LWLockRelease(SInvalReadLock);
+ LWLockRelease(SInvalWriteLock);
+}
+
/*
* GetNextLocalTransactionId --- allocate a new LocalTransactionId
diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h
index 14148bf8201..07d229a5cb2 100644
--- a/src/include/storage/sinvaladt.h
+++ b/src/include/storage/sinvaladt.h
@@ -37,6 +37,7 @@ extern void BackendIdGetTransactionIds(int backendID, TransactionId *xid, Transa
extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n);
extern int SIGetDataEntries(SharedInvalidationMessage *data, int datasize);
extern void SICleanupQueue(bool callerHasWriteLock, int minFree);
+extern void SIResetAll(void);
extern LocalTransactionId GetNextLocalTransactionId(void);