aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/heap/heapam.c33
-rw-r--r--src/backend/access/transam/multixact.c31
2 files changed, 47 insertions, 17 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0524f2efdf3..21e76d6a2a9 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -4183,7 +4183,9 @@ l3:
* the case, HeapTupleSatisfiesUpdate would have returned
* MayBeUpdated and we wouldn't be here.
*/
- nmembers = GetMultiXactIdMembers(xwait, &members, false);
+ nmembers =
+ GetMultiXactIdMembers(xwait, &members, false,
+ HEAP_XMAX_IS_LOCKED_ONLY(infomask));
for (i = 0; i < nmembers; i++)
{
@@ -4204,7 +4206,8 @@ l3:
}
}
- pfree(members);
+ if (members)
+ pfree(members);
}
/*
@@ -4353,7 +4356,9 @@ l3:
* been the case, HeapTupleSatisfiesUpdate would have returned
* MayBeUpdated and we wouldn't be here.
*/
- nmembers = GetMultiXactIdMembers(xwait, &members, false);
+ nmembers =
+ GetMultiXactIdMembers(xwait, &members, false,
+ HEAP_XMAX_IS_LOCKED_ONLY(infomask));
if (nmembers <= 0)
{
@@ -4834,7 +4839,7 @@ l5:
* MultiXactIdExpand if we weren't to do this, so this check is not
* incurring extra work anyhow.
*/
- if (!MultiXactIdIsRunning(xmax))
+ if (!MultiXactIdIsRunning(xmax, HEAP_XMAX_IS_LOCKED_ONLY(old_infomask)))
{
if (HEAP_XMAX_IS_LOCKED_ONLY(old_infomask) ||
TransactionIdDidAbort(MultiXactIdGetUpdateXid(xmax,
@@ -5175,7 +5180,8 @@ l4:
int i;
MultiXactMember *members;
- nmembers = GetMultiXactIdMembers(rawxmax, &members, false);
+ nmembers = GetMultiXactIdMembers(rawxmax, &members, false,
+ HEAP_XMAX_IS_LOCKED_ONLY(old_infomask));
for (i = 0; i < nmembers; i++)
{
HTSU_Result res;
@@ -5533,7 +5539,8 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
*/
Assert((!(t_infomask & HEAP_LOCK_MASK) &&
HEAP_XMAX_IS_LOCKED_ONLY(t_infomask)) ||
- !MultiXactIdIsRunning(multi));
+ !MultiXactIdIsRunning(multi,
+ HEAP_XMAX_IS_LOCKED_ONLY(t_infomask)));
if (HEAP_XMAX_IS_LOCKED_ONLY(t_infomask))
{
*flags |= FRM_INVALIDATE_XMAX;
@@ -5576,7 +5583,9 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
allow_old = !(t_infomask & HEAP_LOCK_MASK) &&
HEAP_XMAX_IS_LOCKED_ONLY(t_infomask);
- nmembers = GetMultiXactIdMembers(multi, &members, allow_old);
+ nmembers =
+ GetMultiXactIdMembers(multi, &members, allow_old,
+ HEAP_XMAX_IS_LOCKED_ONLY(t_infomask));
if (nmembers <= 0)
{
/* Nothing worth keeping */
@@ -5983,7 +5992,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
* We only use this in multis we just created, so they cannot be values
* pre-pg_upgrade.
*/
- nmembers = GetMultiXactIdMembers(multi, &members, false);
+ nmembers = GetMultiXactIdMembers(multi, &members, false, false);
for (i = 0; i < nmembers; i++)
{
@@ -6062,7 +6071,7 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask)
* Since we know the LOCK_ONLY bit is not set, this cannot be a multi from
* pre-pg_upgrade.
*/
- nmembers = GetMultiXactIdMembers(xmax, &members, false);
+ nmembers = GetMultiXactIdMembers(xmax, &members, false, false);
if (nmembers > 0)
{
@@ -6148,7 +6157,8 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status,
int remain = 0;
allow_old = !(infomask & HEAP_LOCK_MASK) && HEAP_XMAX_IS_LOCKED_ONLY(infomask);
- nmembers = GetMultiXactIdMembers(multi, &members, allow_old);
+ nmembers = GetMultiXactIdMembers(multi, &members, allow_old,
+ HEAP_XMAX_IS_LOCKED_ONLY(infomask));
if (nmembers >= 0)
{
@@ -6294,7 +6304,8 @@ heap_tuple_needs_freeze(HeapTupleHeader tuple, TransactionId cutoff_xid,
allow_old = !(tuple->t_infomask & HEAP_LOCK_MASK) &&
HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask);
- nmembers = GetMultiXactIdMembers(multi, &members, allow_old);
+ nmembers = GetMultiXactIdMembers(multi, &members, allow_old,
+ HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
for (i = 0; i < nmembers; i++)
{
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 9f259bb54eb..33346c76643 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -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;
@@ -1133,6 +1138,19 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members,
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.
*
* An ID older than MultiXactState->oldestMultiXactId cannot possibly be
@@ -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);