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)
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