Skip to content

Commit b78647a

Browse files
committed
Restrict infomask bits to set on multixacts
We must only set the bit(s) for the strongest lock held in the tuple; otherwise, a multixact containing members with exclusive lock and key-share lock will behave as though only a share lock is held. This bug was introduced in commit 0ac5ad5, somewhere along development, when we allowed a singleton FOR SHARE lock to be implemented without a MultiXact by using a multi-bit pattern. I overlooked that GetMultiXactIdHintBits() needed to be tweaked as well. Previously, we could have the bits for FOR KEY SHARE and FOR UPDATE simultaneously set and it wouldn't cause a problem. Per report from digoal@126.com
1 parent 77a3082 commit b78647a

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

src/backend/access/heap/heapam.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3269,7 +3269,13 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
32693269
&xmax_old_tuple, &infomask_old_tuple,
32703270
&infomask2_old_tuple);
32713271

3272-
/* And also prepare an Xmax value for the new copy of the tuple */
3272+
/*
3273+
* And also prepare an Xmax value for the new copy of the tuple. If there
3274+
* was no xmax previously, or there was one but all lockers are now gone,
3275+
* then use InvalidXid; otherwise, get the xmax from the old tuple. (In
3276+
* rare cases that might also be InvalidXid and yet not have the
3277+
* HEAP_XMAX_INVALID bit set; that's fine.)
3278+
*/
32733279
if ((oldtup.t_data->t_infomask & HEAP_XMAX_INVALID) ||
32743280
(checked_lockers && !locker_remains))
32753281
xmax_new_tuple = InvalidTransactionId;
@@ -3283,6 +3289,12 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
32833289
}
32843290
else
32853291
{
3292+
/*
3293+
* If we found a valid Xmax for the new tuple, then the infomask bits
3294+
* to use on the new tuple depend on what was there on the old one.
3295+
* Note that since we're doing an update, the only possibility is that
3296+
* the lockers had FOR KEY SHARE lock.
3297+
*/
32863298
if (oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI)
32873299
{
32883300
GetMultiXactIdHintBits(xmax_new_tuple, &infomask_new_tuple,
@@ -5161,6 +5173,7 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
51615173
uint16 bits = HEAP_XMAX_IS_MULTI;
51625174
uint16 bits2 = 0;
51635175
bool has_update = false;
5176+
LockTupleMode strongest = LockTupleKeyShare;
51645177

51655178
/*
51665179
* We only use this in multis we just created, so they cannot be values
@@ -5170,32 +5183,47 @@ GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
51705183

51715184
for (i = 0; i < nmembers; i++)
51725185
{
5186+
LockTupleMode mode;
5187+
5188+
/*
5189+
* Remember the strongest lock mode held by any member of the
5190+
* multixact.
5191+
*/
5192+
mode = TUPLOCK_from_mxstatus(members[i].status);
5193+
if (mode > strongest)
5194+
strongest = mode;
5195+
5196+
/* See what other bits we need */
51735197
switch (members[i].status)
51745198
{
51755199
case MultiXactStatusForKeyShare:
5176-
bits |= HEAP_XMAX_KEYSHR_LOCK;
5177-
break;
51785200
case MultiXactStatusForShare:
5179-
bits |= HEAP_XMAX_SHR_LOCK;
5180-
break;
51815201
case MultiXactStatusForNoKeyUpdate:
5182-
bits |= HEAP_XMAX_EXCL_LOCK;
51835202
break;
5203+
51845204
case MultiXactStatusForUpdate:
5185-
bits |= HEAP_XMAX_EXCL_LOCK;
51865205
bits2 |= HEAP_KEYS_UPDATED;
51875206
break;
5207+
51885208
case MultiXactStatusNoKeyUpdate:
5189-
bits |= HEAP_XMAX_EXCL_LOCK;
51905209
has_update = true;
51915210
break;
5211+
51925212
case MultiXactStatusUpdate:
5193-
bits |= HEAP_XMAX_EXCL_LOCK;
51945213
bits2 |= HEAP_KEYS_UPDATED;
51955214
has_update = true;
51965215
break;
51975216
}
51985217
}
5218+
5219+
if (strongest == LockTupleExclusive ||
5220+
strongest == LockTupleNoKeyExclusive)
5221+
bits |= HEAP_XMAX_EXCL_LOCK;
5222+
else if (strongest == LockTupleShare)
5223+
bits |= HEAP_XMAX_SHR_LOCK;
5224+
else if (strongest == LockTupleKeyShare)
5225+
bits |= HEAP_XMAX_KEYSHR_LOCK;
5226+
51995227
if (!has_update)
52005228
bits |= HEAP_XMAX_LOCK_ONLY;
52015229

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy