Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita4668c9

Browse files
committed
At end of recovery, reset all sinval-managed caches.
An inplace update's invalidation messages are part of its transaction'scommit record. However, the update survives even if its transactionaborts or we stop recovery before replaying its transaction commit.After recovery, a backend that started in recovery could update the rowwithout incorporating the inplace update. That could result in a tablewith an index, yet relhasindex=f. That is a source of index corruption.This bulk invalidation avoids the functional consequences. A futurechange can fix the !RecoveryInProgress() scenario without changing theWAL format. Back-patch to v17 - v12 (all supported versions). v18 willinstead add invalidations to WAL.Discussion:https://postgr.es/m/20240618152349.7f.nmisch@google.com
1 parente119076 commita4668c9

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

‎src/backend/access/transam/xlog.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#include"storage/proc.h"
9393
#include"storage/procarray.h"
9494
#include"storage/reinit.h"
95+
#include"storage/sinvaladt.h"
9596
#include"storage/spin.h"
9697
#include"storage/sync.h"
9798
#include"utils/guc_hooks.h"
@@ -6037,6 +6038,30 @@ StartupXLOG(void)
60376038
XLogCtl->LogwrtRqst.Write=EndOfLog;
60386039
XLogCtl->LogwrtRqst.Flush=EndOfLog;
60396040

6041+
/*
6042+
* Invalidate all sinval-managed caches before READ WRITE transactions
6043+
* begin. The xl_heap_inplace WAL record doesn't store sufficient data
6044+
* for invalidations. The commit record, if any, has the invalidations.
6045+
* However, the inplace update is permanent, whether or not we reach a
6046+
* commit record. Fortunately, read-only transactions tolerate caches not
6047+
* reflecting the latest inplace updates. Read-only transactions
6048+
* experience the notable inplace updates as follows:
6049+
*
6050+
* - relhasindex=true affects readers only after the CREATE INDEX
6051+
* transaction commit makes an index fully available to them.
6052+
*
6053+
* - datconnlimit=DATCONNLIMIT_INVALID_DB affects readers only at
6054+
* InitPostgres() time, and that read does not use a cache.
6055+
*
6056+
* - relfrozenxid, datfrozenxid, relminmxid, and datminmxid have no effect
6057+
* on readers.
6058+
*
6059+
* Hence, hot standby queries (all READ ONLY) function correctly without
6060+
* the missing invalidations. This avoided changing the WAL format in
6061+
* back branches.
6062+
*/
6063+
SIResetAll();
6064+
60406065
/*
60416066
* Preallocate additional log files, if wanted.
60426067
*/

‎src/backend/storage/ipc/sinvaladt.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,48 @@ SICleanupQueue(bool callerHasWriteLock, int minFree)
683683
}
684684
}
685685

686+
/*
687+
* SIResetAll
688+
*Mark all active backends as "reset"
689+
*
690+
* Use this when we don't know what needs to be invalidated. It's a
691+
* cluster-wide InvalidateSystemCaches(). This was a back-branch-only remedy
692+
* to avoid a WAL format change.
693+
*
694+
* The implementation is like SICleanupQueue(false, MAXNUMMESSAGES + 1), with
695+
* one addition. SICleanupQueue() assumes minFree << MAXNUMMESSAGES, so it
696+
* assumes hasMessages==true for any backend it resets. We're resetting even
697+
* fully-caught-up backends, so we set hasMessages.
698+
*/
699+
void
700+
SIResetAll(void)
701+
{
702+
SISeg*segP=shmInvalBuffer;
703+
inti;
704+
705+
LWLockAcquire(SInvalWriteLock,LW_EXCLUSIVE);
706+
LWLockAcquire(SInvalReadLock,LW_EXCLUSIVE);
707+
708+
for (i=0;i<segP->numProcs;i++)
709+
{
710+
ProcState*stateP=&segP->procState[segP->pgprocnos[i]];
711+
712+
Assert(stateP->procPid!=0);
713+
if (stateP->sendOnly)
714+
continue;
715+
716+
/* Consuming the reset will update "nextMsgNum" and "signaled". */
717+
stateP->resetState= true;
718+
stateP->hasMessages= true;
719+
}
720+
721+
segP->minMsgNum=segP->maxMsgNum;
722+
segP->nextThreshold=CLEANUP_MIN;
723+
724+
LWLockRelease(SInvalReadLock);
725+
LWLockRelease(SInvalWriteLock);
726+
}
727+
686728

687729
/*
688730
* GetNextLocalTransactionId --- allocate a new LocalTransactionId

‎src/include/storage/sinvaladt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern void SharedInvalBackendInit(bool sendOnly);
3535
externvoidSIInsertDataEntries(constSharedInvalidationMessage*data,intn);
3636
externintSIGetDataEntries(SharedInvalidationMessage*data,intdatasize);
3737
externvoidSICleanupQueue(boolcallerHasWriteLock,intminFree);
38+
externvoidSIResetAll(void);
3839

3940
externLocalTransactionIdGetNextLocalTransactionId(void);
4041

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp