Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 30d47ec

Browse files
committed
Unpin buffer before inplace update waits for an XID to end.
Commit a07e03f changed inplace updates to wait for heap_update() commands like GRANT TABLE and GRANT DATABASE. By keeping the pin during that wait, a sequence of autovacuum workers and an uncommitted GRANT starved one foreground LockBufferForCleanup() for six minutes, on buildfarm member sarus. Prevent, at the cost of a bit of complexity. Back-patch to v12, like the earlier commit. That commit and heap_inplace_lock() have not yet appeared in any release. Discussion: https://postgr.es/m/20241026184936.ae.nmisch@google.com
1 parent 502e7bf commit 30d47ec

File tree

3 files changed

+14
-11
lines changed

3 files changed

+14
-11
lines changed

src/backend/access/heap/heapam.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6165,8 +6165,8 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
61656165
* transaction. If compatible, return true with the buffer exclusive-locked,
61666166
* and the caller must release that by calling
61676167
* heap_inplace_update_and_unlock(), calling heap_inplace_unlock(), or raising
6168-
* an error. Otherwise, return false after blocking transactions, if any,
6169-
* have ended.
6168+
* an error. Otherwise, call release_callback(arg), wait for blocking
6169+
* transactions to end, and return false.
61706170
*
61716171
* Since this is intended for system catalogs and SERIALIZABLE doesn't cover
61726172
* DDL, this doesn't guarantee any particular predicate locking.
@@ -6200,7 +6200,8 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
62006200
*/
62016201
bool
62026202
heap_inplace_lock(Relation relation,
6203-
HeapTuple oldtup_ptr, Buffer buffer)
6203+
HeapTuple oldtup_ptr, Buffer buffer,
6204+
void (*release_callback) (void *), void *arg)
62046205
{
62056206
HeapTupleData oldtup = *oldtup_ptr; /* minimize diff vs. heap_update() */
62066207
TM_Result result;
@@ -6265,6 +6266,7 @@ heap_inplace_lock(Relation relation,
62656266
lockmode, NULL))
62666267
{
62676268
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6269+
release_callback(arg);
62686270
ret = false;
62696271
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
62706272
relation, &oldtup.t_self, XLTW_Update,
@@ -6280,6 +6282,7 @@ heap_inplace_lock(Relation relation,
62806282
else
62816283
{
62826284
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6285+
release_callback(arg);
62836286
ret = false;
62846287
XactLockTableWait(xwait, relation, &oldtup.t_self,
62856288
XLTW_Update);
@@ -6291,6 +6294,7 @@ heap_inplace_lock(Relation relation,
62916294
if (!ret)
62926295
{
62936296
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6297+
release_callback(arg);
62946298
}
62956299
}
62966300

src/backend/access/index/genam.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ systable_inplace_update_begin(Relation relation,
814814
int retries = 0;
815815
SysScanDesc scan;
816816
HeapTuple oldtup;
817+
BufferHeapTupleTableSlot *bslot;
817818

818819
/*
819820
* For now, we don't allow parallel updates. Unlike a regular update,
@@ -835,10 +836,9 @@ systable_inplace_update_begin(Relation relation,
835836
Assert(IsInplaceUpdateRelation(relation) || !IsSystemRelation(relation));
836837

837838
/* Loop for an exclusive-locked buffer of a non-updated tuple. */
838-
for (;;)
839+
do
839840
{
840841
TupleTableSlot *slot;
841-
BufferHeapTupleTableSlot *bslot;
842842

843843
CHECK_FOR_INTERRUPTS();
844844

@@ -864,11 +864,9 @@ systable_inplace_update_begin(Relation relation,
864864
slot = scan->slot;
865865
Assert(TTS_IS_BUFFERTUPLE(slot));
866866
bslot = (BufferHeapTupleTableSlot *) slot;
867-
if (heap_inplace_lock(scan->heap_rel,
868-
bslot->base.tuple, bslot->buffer))
869-
break;
870-
systable_endscan(scan);
871-
};
867+
} while (!heap_inplace_lock(scan->heap_rel,
868+
bslot->base.tuple, bslot->buffer,
869+
(void (*) (void *)) systable_endscan, scan));
872870

873871
*oldtupcopy = heap_copytuple(oldtup);
874872
*state = scan;

src/include/access/heapam.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
338338
Buffer *buffer, struct TM_FailureData *tmfd);
339339

340340
extern bool heap_inplace_lock(Relation relation,
341-
HeapTuple oldtup_ptr, Buffer buffer);
341+
HeapTuple oldtup_ptr, Buffer buffer,
342+
void (*release_callback) (void *), void *arg);
342343
extern void heap_inplace_update_and_unlock(Relation relation,
343344
HeapTuple oldtup, HeapTuple tuple,
344345
Buffer buffer);

0 commit comments

Comments
 (0)