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

Commitd36b4d8

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 parent2d63c96 commitd36b4d8

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
#include"storage/proc.h"
9595
#include"storage/procarray.h"
9696
#include"storage/reinit.h"
97+
#include"storage/sinvaladt.h"
9798
#include"storage/smgr.h"
9899
#include"storage/spin.h"
99100
#include"storage/sync.h"
@@ -5659,6 +5660,30 @@ StartupXLOG(void)
56595660
XLogCtl->LogwrtRqst.Write=EndOfLog;
56605661
XLogCtl->LogwrtRqst.Flush=EndOfLog;
56615662

5663+
/*
5664+
* Invalidate all sinval-managed caches before READ WRITE transactions
5665+
* begin. The xl_heap_inplace WAL record doesn't store sufficient data
5666+
* for invalidations. The commit record, if any, has the invalidations.
5667+
* However, the inplace update is permanent, whether or not we reach a
5668+
* commit record. Fortunately, read-only transactions tolerate caches not
5669+
* reflecting the latest inplace updates. Read-only transactions
5670+
* experience the notable inplace updates as follows:
5671+
*
5672+
* - relhasindex=true affects readers only after the CREATE INDEX
5673+
* transaction commit makes an index fully available to them.
5674+
*
5675+
* - datconnlimit=DATCONNLIMIT_INVALID_DB affects readers only at
5676+
* InitPostgres() time, and that read does not use a cache.
5677+
*
5678+
* - relfrozenxid, datfrozenxid, relminmxid, and datminmxid have no effect
5679+
* on readers.
5680+
*
5681+
* Hence, hot standby queries (all READ ONLY) function correctly without
5682+
* the missing invalidations. This avoided changing the WAL format in
5683+
* back branches.
5684+
*/
5685+
SIResetAll();
5686+
56625687
/*
56635688
* Preallocate additional log files, if wanted.
56645689
*/

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,47 @@ SICleanupQueue(bool callerHasWriteLock, int minFree)
762762
}
763763
}
764764

765+
/*
766+
* SIResetAll
767+
*Mark all active backends as "reset"
768+
*
769+
* Use this when we don't know what needs to be invalidated. It's a
770+
* cluster-wide InvalidateSystemCaches(). This was a back-branch-only remedy
771+
* to avoid a WAL format change.
772+
*
773+
* The implementation is like SICleanupQueue(false, MAXNUMMESSAGES + 1), with
774+
* one addition. SICleanupQueue() assumes minFree << MAXNUMMESSAGES, so it
775+
* assumes hasMessages==true for any backend it resets. We're resetting even
776+
* fully-caught-up backends, so we set hasMessages.
777+
*/
778+
void
779+
SIResetAll(void)
780+
{
781+
SISeg*segP=shmInvalBuffer;
782+
inti;
783+
784+
LWLockAcquire(SInvalWriteLock,LW_EXCLUSIVE);
785+
LWLockAcquire(SInvalReadLock,LW_EXCLUSIVE);
786+
787+
for (i=0;i<segP->lastBackend;i++)
788+
{
789+
ProcState*stateP=&segP->procState[i];
790+
791+
if (stateP->procPid==0||stateP->sendOnly)
792+
continue;
793+
794+
/* Consuming the reset will update "nextMsgNum" and "signaled". */
795+
stateP->resetState= true;
796+
stateP->hasMessages= true;
797+
}
798+
799+
segP->minMsgNum=segP->maxMsgNum;
800+
segP->nextThreshold=CLEANUP_MIN;
801+
802+
LWLockRelease(SInvalReadLock);
803+
LWLockRelease(SInvalWriteLock);
804+
}
805+
765806

766807
/*
767808
* GetNextLocalTransactionId --- allocate a new LocalTransactionId

‎src/include/storage/sinvaladt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern void BackendIdGetTransactionIds(int backendID, TransactionId *xid,
3939
externvoidSIInsertDataEntries(constSharedInvalidationMessage*data,intn);
4040
externintSIGetDataEntries(SharedInvalidationMessage*data,intdatasize);
4141
externvoidSICleanupQueue(boolcallerHasWriteLock,intminFree);
42+
externvoidSIResetAll(void);
4243

4344
externLocalTransactionIdGetNextLocalTransactionId(void);
4445

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp