mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
Rewrite the sinval messaging mechanism to reduce contention and avoid
unnecessary cache resets. The major changes are: * When the queue overflows, we only issue a cache reset to the specific backend or backends that still haven't read the oldest message, rather than resetting everyone as in the original coding. * When we observe backend(s) falling well behind, we signal SIGUSR1 to only one backend, the one that is furthest behind and doesn't already have a signal outstanding for it. When it finishes catching up, it will in turn signal SIGUSR1 to the next-furthest-back guy, if there is one that is far enough behind to justify a signal. The PMSIGNAL_WAKEN_CHILDREN mechanism is removed. * We don't attempt to clean out dead messages after every message-receipt operation; rather, we do it on the insertion side, and only when the queue fullness passes certain thresholds. * Split SInvalLock into SInvalReadLock and SInvalWriteLock so that readers don't block writers nor vice versa (except during the infrequent queue cleanout operations). * Transfer multiple sinval messages for each acquisition of a read or write lock.
This commit is contained in:
43
src/backend/utils/cache/inval.c
vendored
43
src/backend/utils/cache/inval.c
vendored
@ -80,7 +80,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.85 2008/06/19 00:46:05 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.86 2008/06/19 21:32:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -203,7 +203,7 @@ AddInvalidationMessage(InvalidationChunk **listHdr,
|
||||
if (chunk == NULL)
|
||||
{
|
||||
/* First time through; create initial chunk */
|
||||
#define FIRSTCHUNKSIZE 16
|
||||
#define FIRSTCHUNKSIZE 32
|
||||
chunk = (InvalidationChunk *)
|
||||
MemoryContextAlloc(CurTransactionContext,
|
||||
sizeof(InvalidationChunk) +
|
||||
@ -275,6 +275,23 @@ AppendInvalidationMessageList(InvalidationChunk **destHdr,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Process a list of invalidation messages group-wise.
|
||||
*
|
||||
* As above, but the code fragment can handle an array of messages.
|
||||
* The fragment should refer to the messages as msgs[], with n entries.
|
||||
*/
|
||||
#define ProcessMessageListMulti(listHdr, codeFragment) \
|
||||
do { \
|
||||
InvalidationChunk *_chunk; \
|
||||
for (_chunk = (listHdr); _chunk != NULL; _chunk = _chunk->next) \
|
||||
{ \
|
||||
SharedInvalidationMessage *msgs = _chunk->msgs; \
|
||||
int n = _chunk->nitems; \
|
||||
codeFragment; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Invalidation set support functions
|
||||
@ -371,6 +388,18 @@ ProcessInvalidationMessages(InvalidationListHeader *hdr,
|
||||
ProcessMessageList(hdr->rclist, func(msg));
|
||||
}
|
||||
|
||||
/*
|
||||
* As above, but the function is able to process an array of messages
|
||||
* rather than just one at a time.
|
||||
*/
|
||||
static void
|
||||
ProcessInvalidationMessagesMulti(InvalidationListHeader *hdr,
|
||||
void (*func) (const SharedInvalidationMessage *msgs, int n))
|
||||
{
|
||||
ProcessMessageListMulti(hdr->cclist, func(msgs, n));
|
||||
ProcessMessageListMulti(hdr->rclist, func(msgs, n));
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* private support functions
|
||||
* ----------------------------------------------------------------
|
||||
@ -792,7 +821,7 @@ inval_twophase_postcommit(TransactionId xid, uint16 info,
|
||||
case TWOPHASE_INFO_MSG:
|
||||
msg = (SharedInvalidationMessage *) recdata;
|
||||
Assert(len == sizeof(SharedInvalidationMessage));
|
||||
SendSharedInvalidMessage(msg);
|
||||
SendSharedInvalidMessages(msg, 1);
|
||||
break;
|
||||
case TWOPHASE_INFO_FILE_BEFORE:
|
||||
RelationCacheInitFileInvalidate(true);
|
||||
@ -850,8 +879,8 @@ AtEOXact_Inval(bool isCommit)
|
||||
AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs,
|
||||
&transInvalInfo->CurrentCmdInvalidMsgs);
|
||||
|
||||
ProcessInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs,
|
||||
SendSharedInvalidMessage);
|
||||
ProcessInvalidationMessagesMulti(&transInvalInfo->PriorCmdInvalidMsgs,
|
||||
SendSharedInvalidMessages);
|
||||
|
||||
if (transInvalInfo->RelcacheInitFileInval)
|
||||
RelationCacheInitFileInvalidate(false);
|
||||
@ -1033,8 +1062,8 @@ EndNonTransactionalInvalidation(void)
|
||||
/* Send out the invals */
|
||||
ProcessInvalidationMessages(&transInvalInfo->CurrentCmdInvalidMsgs,
|
||||
LocalExecuteInvalidationMessage);
|
||||
ProcessInvalidationMessages(&transInvalInfo->CurrentCmdInvalidMsgs,
|
||||
SendSharedInvalidMessage);
|
||||
ProcessInvalidationMessagesMulti(&transInvalInfo->CurrentCmdInvalidMsgs,
|
||||
SendSharedInvalidMessages);
|
||||
|
||||
/* Clean up and release memory */
|
||||
for (chunk = transInvalInfo->CurrentCmdInvalidMsgs.cclist;
|
||||
|
Reference in New Issue
Block a user