@@ -105,11 +105,12 @@ static void GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
105105 uint16 * new_infomask2 );
106106static TransactionId MultiXactIdGetUpdateXid (TransactionId xmax ,
107107 uint16 t_infomask );
108- static void MultiXactIdWait (MultiXactId multi , MultiXactStatus status ,
109- int * remaining , uint16 infomask );
110- static bool ConditionalMultiXactIdWait (MultiXactId multi ,
111- MultiXactStatus status , int * remaining ,
112- uint16 infomask );
108+ static void MultiXactIdWait (MultiXactId multi , MultiXactStatus status , uint16 infomask ,
109+ Relation rel , ItemPointer ctid , XLTW_Oper oper ,
110+ int * remaining );
111+ static bool ConditionalMultiXactIdWait (MultiXactId multi , MultiXactStatus status ,
112+ uint16 infomask , Relation rel , ItemPointer ctid ,
113+ XLTW_Oper oper , int * remaining );
113114static XLogRecPtr log_heap_new_cid (Relation relation , HeapTuple tup );
114115static HeapTuple ExtractReplicaIdentity (Relation rel , HeapTuple tup , bool key_modified ,
115116 bool * copy );
@@ -2714,8 +2715,9 @@ heap_delete(Relation relation, ItemPointer tid,
27142715 if (infomask & HEAP_XMAX_IS_MULTI )
27152716 {
27162717 /* wait for multixact */
2717- MultiXactIdWait ((MultiXactId ) xwait , MultiXactStatusUpdate ,
2718- NULL , infomask );
2718+ MultiXactIdWait ((MultiXactId ) xwait , MultiXactStatusUpdate , infomask ,
2719+ relation , & tp .t_data -> t_ctid , XLTW_Delete ,
2720+ NULL );
27192721 LockBuffer (buffer , BUFFER_LOCK_EXCLUSIVE );
27202722
27212723 /*
@@ -2741,7 +2743,7 @@ heap_delete(Relation relation, ItemPointer tid,
27412743 else
27422744 {
27432745 /* wait for regular transaction to end */
2744- XactLockTableWait (xwait );
2746+ XactLockTableWait (xwait , relation , & tp . t_data -> t_ctid , XLTW_Delete );
27452747 LockBuffer (buffer , BUFFER_LOCK_EXCLUSIVE );
27462748
27472749 /*
@@ -3266,8 +3268,9 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
32663268 int remain ;
32673269
32683270 /* wait for multixact */
3269- MultiXactIdWait ((MultiXactId ) xwait , mxact_status , & remain ,
3270- infomask );
3271+ MultiXactIdWait ((MultiXactId ) xwait , mxact_status , infomask ,
3272+ relation , & oldtup .t_data -> t_ctid , XLTW_Update ,
3273+ & remain );
32713274 LockBuffer (buffer , BUFFER_LOCK_EXCLUSIVE );
32723275
32733276 /*
@@ -3341,7 +3344,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
33413344 else
33423345 {
33433346 /* wait for regular transaction to end */
3344- XactLockTableWait (xwait );
3347+ XactLockTableWait (xwait , relation , & oldtup .t_data -> t_ctid ,
3348+ XLTW_Update );
33453349 LockBuffer (buffer , BUFFER_LOCK_EXCLUSIVE );
33463350
33473351 /*
@@ -4402,14 +4406,18 @@ heap_lock_tuple(Relation relation, HeapTuple tuple,
44024406 if (nowait )
44034407 {
44044408 if (!ConditionalMultiXactIdWait ((MultiXactId ) xwait ,
4405- status , NULL , infomask ))
4409+ status , infomask , relation ,
4410+ & tuple -> t_data -> t_ctid ,
4411+ XLTW_Lock , NULL ))
44064412 ereport (ERROR ,
44074413 (errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
44084414 errmsg ("could not obtain lock on row in relation \"%s\"" ,
44094415 RelationGetRelationName (relation ))));
44104416 }
44114417 else
4412- MultiXactIdWait ((MultiXactId ) xwait , status , NULL , infomask );
4418+ MultiXactIdWait ((MultiXactId ) xwait , status , infomask ,
4419+ relation , & tuple -> t_data -> t_ctid ,
4420+ XLTW_Lock , NULL );
44134421
44144422 /* if there are updates, follow the update chain */
44154423 if (follow_updates &&
@@ -4464,7 +4472,8 @@ heap_lock_tuple(Relation relation, HeapTuple tuple,
44644472 RelationGetRelationName (relation ))));
44654473 }
44664474 else
4467- XactLockTableWait (xwait );
4475+ XactLockTableWait (xwait , relation , & tuple -> t_data -> t_ctid ,
4476+ XLTW_Lock );
44684477
44694478 /* if there are updates, follow the update chain */
44704479 if (follow_updates &&
@@ -5151,7 +5160,9 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
51515160 if (needwait )
51525161 {
51535162 LockBuffer (buf , BUFFER_LOCK_UNLOCK );
5154- XactLockTableWait (members [i ].xid );
5163+ XactLockTableWait (members [i ].xid , rel ,
5164+ & mytup .t_data -> t_ctid ,
5165+ XLTW_LockUpdated );
51555166 pfree (members );
51565167 goto l4 ;
51575168 }
@@ -5211,7 +5222,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
52115222 if (needwait )
52125223 {
52135224 LockBuffer (buf , BUFFER_LOCK_UNLOCK );
5214- XactLockTableWait (rawxmax );
5225+ XactLockTableWait (rawxmax , rel , & mytup .t_data -> t_ctid ,
5226+ XLTW_LockUpdated );
52155227 goto l4 ;
52165228 }
52175229 if (res != HeapTupleMayBeUpdated )
@@ -6076,6 +6088,15 @@ HeapTupleGetUpdateXid(HeapTupleHeader tuple)
60766088 * Do_MultiXactIdWait
60776089 * Actual implementation for the two functions below.
60786090 *
6091+ * 'multi', 'status' and 'infomask' indicate what to sleep on (the status is
6092+ * needed to ensure we only sleep on conflicting members, and the infomask is
6093+ * used to optimize multixact access in case it's a lock-only multi); 'nowait'
6094+ * indicates whether to use conditional lock acquisition, to allow callers to
6095+ * fail if lock is unavailable. 'rel', 'ctid' and 'oper' are used to set up
6096+ * context information for error messages. 'remaining', if not NULL, receives
6097+ * the number of members that are still running, including any (non-aborted)
6098+ * subtransactions of our own transaction.
6099+ *
60796100 * We do this by sleeping on each member using XactLockTableWait. Any
60806101 * members that belong to the current backend are *not* waited for, however;
60816102 * this would not merely be useless but would lead to Assert failure inside
@@ -6093,7 +6114,9 @@ HeapTupleGetUpdateXid(HeapTupleHeader tuple)
60936114 */
60946115static bool
60956116Do_MultiXactIdWait (MultiXactId multi , MultiXactStatus status ,
6096- int * remaining , uint16 infomask , bool nowait )
6117+ uint16 infomask , bool nowait ,
6118+ Relation rel , ItemPointer ctid , XLTW_Oper oper ,
6119+ int * remaining )
60976120{
60986121 bool allow_old ;
60996122 bool result = true;
@@ -6130,6 +6153,12 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status,
61306153 /*
61316154 * This member conflicts with our multi, so we have to sleep (or
61326155 * return failure, if asked to avoid waiting.)
6156+ *
6157+ * Note that we don't set up an error context callback ourselves,
6158+ * but instead we pass the info down to XactLockTableWait. This
6159+ * might seem a bit wasteful because the context is set up and
6160+ * tore down for each member of the multixact, but in reality it
6161+ * should be barely noticeable, and it avoids duplicate code.
61336162 */
61346163 if (nowait )
61356164 {
@@ -6138,7 +6167,7 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status,
61386167 break ;
61396168 }
61406169 else
6141- XactLockTableWait (memxid );
6170+ XactLockTableWait (memxid , rel , ctid , oper );
61426171 }
61436172
61446173 pfree (members );
@@ -6159,13 +6188,14 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status,
61596188 *
61606189 * We return (in *remaining, if not NULL) the number of members that are still
61616190 * running, including any (non-aborted) subtransactions of our own transaction.
6162- *
61636191 */
61646192static void
6165- MultiXactIdWait (MultiXactId multi , MultiXactStatus status ,
6166- int * remaining , uint16 infomask )
6193+ MultiXactIdWait (MultiXactId multi , MultiXactStatus status , uint16 infomask ,
6194+ Relation rel , ItemPointer ctid , XLTW_Oper oper ,
6195+ int * remaining )
61676196{
6168- Do_MultiXactIdWait (multi , status , remaining , infomask , false);
6197+ (void ) Do_MultiXactIdWait (multi , status , infomask , false,
6198+ rel , ctid , oper , remaining );
61696199}
61706200
61716201/*
@@ -6183,9 +6213,11 @@ MultiXactIdWait(MultiXactId multi, MultiXactStatus status,
61836213 */
61846214static bool
61856215ConditionalMultiXactIdWait (MultiXactId multi , MultiXactStatus status ,
6186- int * remaining , uint16 infomask )
6216+ uint16 infomask , Relation rel , ItemPointer ctid ,
6217+ XLTW_Oper oper , int * remaining )
61876218{
6188- return Do_MultiXactIdWait (multi , status , remaining , infomask , true);
6219+ return Do_MultiXactIdWait (multi , status , infomask , true,
6220+ rel , ctid , oper , remaining );
61896221}
61906222
61916223/*
0 commit comments