mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Avoid uselessly looking up old LOCK_ONLY multixacts
Commit 0ac5ad5134
removed an optimization in multixact.c that skipped
fetching members of MultiXactId that were older than our
OldestVisibleMXactId value. The reason this was removed is that it is
possible for multixacts that contain updates to be older than that
value. However, if the caller is certain that the multi does not
contain an update (because the infomask bits say so), it can pass this
info down to GetMultiXactIdMembers, enabling it to use the old
optimization.
Pointed out by Andres Freund in 20131121200517.GM7240@alap2.anarazel.de
This commit is contained in:
@ -428,7 +428,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
|
||||
* caller of this function does a check that the multixact is no longer
|
||||
* running.
|
||||
*/
|
||||
nmembers = GetMultiXactIdMembers(multi, &members, false);
|
||||
nmembers = GetMultiXactIdMembers(multi, &members, false, false);
|
||||
|
||||
if (nmembers < 0)
|
||||
{
|
||||
@ -517,7 +517,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
|
||||
* a pg_upgraded share-locked tuple.
|
||||
*/
|
||||
bool
|
||||
MultiXactIdIsRunning(MultiXactId multi)
|
||||
MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
|
||||
{
|
||||
MultiXactMember *members;
|
||||
int nmembers;
|
||||
@ -529,7 +529,7 @@ MultiXactIdIsRunning(MultiXactId multi)
|
||||
* "false" here means we assume our callers have checked that the given
|
||||
* multi cannot possibly come from a pg_upgraded database.
|
||||
*/
|
||||
nmembers = GetMultiXactIdMembers(multi, &members, false);
|
||||
nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly);
|
||||
|
||||
if (nmembers < 0)
|
||||
{
|
||||
@ -1095,10 +1095,15 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
|
||||
* the value currently known as the next to assign, raise an error. Previously
|
||||
* these also returned -1, but since this can lead to the wrong visibility
|
||||
* results, it is dangerous to do that.
|
||||
*
|
||||
* onlyLock must be set to true if caller is certain that the given multi
|
||||
* is used only to lock tuples; can be false without loss of correctness,
|
||||
* but passing a true means we can return quickly without checking for
|
||||
* old updates.
|
||||
*/
|
||||
int
|
||||
GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
|
||||
bool allow_old)
|
||||
bool allow_old, bool onlyLock)
|
||||
{
|
||||
int pageno;
|
||||
int prev_pageno;
|
||||
@ -1132,6 +1137,19 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
|
||||
/* Set our OldestVisibleMXactId[] entry if we didn't already */
|
||||
MultiXactIdSetOldestVisible();
|
||||
|
||||
/*
|
||||
* If we know the multi is used only for locking and not for updates,
|
||||
* then we can skip checking if the value is older than our oldest
|
||||
* visible multi. It cannot possibly still be running.
|
||||
*/
|
||||
if (onlyLock &&
|
||||
MultiXactIdPrecedes(multi, OldestVisibleMXactId[MyBackendId]))
|
||||
{
|
||||
debug_elog2(DEBUG2, "GetMembers: a locker-only multi is too old");
|
||||
*members = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We check known limits on MultiXact before resorting to the SLRU area.
|
||||
*
|
||||
@ -1335,7 +1353,7 @@ MultiXactHasRunningRemoteMembers(MultiXactId multi)
|
||||
int nmembers;
|
||||
int i;
|
||||
|
||||
nmembers = GetMultiXactIdMembers(multi, &members, true);
|
||||
nmembers = GetMultiXactIdMembers(multi, &members, true, false);
|
||||
if (nmembers <= 0)
|
||||
return false;
|
||||
|
||||
@ -2807,7 +2825,8 @@ pg_get_multixact_members(PG_FUNCTION_ARGS)
|
||||
|
||||
multi = palloc(sizeof(mxact));
|
||||
/* no need to allow for old values here */
|
||||
multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false);
|
||||
multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
|
||||
false);
|
||||
multi->iter = 0;
|
||||
|
||||
tupdesc = CreateTemplateTupleDesc(2, false);
|
||||
|
Reference in New Issue
Block a user