Skip to content

Commit 9aef6f1

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 cad6590 commit 9aef6f1

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
@@ -6183,8 +6183,8 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
61836183
* transaction. If compatible, return true with the buffer exclusive-locked,
61846184
* and the caller must release that by calling
61856185
* heap_inplace_update_and_unlock(), calling heap_inplace_unlock(), or raising
6186-
* an error. Otherwise, return false after blocking transactions, if any,
6187-
* have ended.
6186+
* an error. Otherwise, call release_callback(arg), wait for blocking
6187+
* transactions to end, and return false.
61886188
*
61896189
* Since this is intended for system catalogs and SERIALIZABLE doesn't cover
61906190
* DDL, this doesn't guarantee any particular predicate locking.
@@ -6218,7 +6218,8 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
62186218
*/
62196219
bool
62206220
heap_inplace_lock(Relation relation,
6221-
HeapTuple oldtup_ptr, Buffer buffer)
6221+
HeapTuple oldtup_ptr, Buffer buffer,
6222+
void (*release_callback) (void *), void *arg)
62226223
{
62236224
HeapTupleData oldtup = *oldtup_ptr; /* minimize diff vs. heap_update() */
62246225
TM_Result result;
@@ -6283,6 +6284,7 @@ heap_inplace_lock(Relation relation,
62836284
lockmode, NULL))
62846285
{
62856286
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6287+
release_callback(arg);
62866288
ret = false;
62876289
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
62886290
relation, &oldtup.t_self, XLTW_Update,
@@ -6298,6 +6300,7 @@ heap_inplace_lock(Relation relation,
62986300
else
62996301
{
63006302
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6303+
release_callback(arg);
63016304
ret = false;
63026305
XactLockTableWait(xwait, relation, &oldtup.t_self,
63036306
XLTW_Update);
@@ -6309,6 +6312,7 @@ heap_inplace_lock(Relation relation,
63096312
if (!ret)
63106313
{
63116314
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
6315+
release_callback(arg);
63126316
}
63136317
}
63146318

src/backend/access/index/genam.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ systable_inplace_update_begin(Relation relation,
804804
int retries = 0;
805805
SysScanDesc scan;
806806
HeapTuple oldtup;
807+
BufferHeapTupleTableSlot *bslot;
807808

808809
/*
809810
* For now, we don't allow parallel updates. Unlike a regular update,
@@ -825,10 +826,9 @@ systable_inplace_update_begin(Relation relation,
825826
Assert(IsInplaceUpdateRelation(relation) || !IsSystemRelation(relation));
826827

827828
/* Loop for an exclusive-locked buffer of a non-updated tuple. */
828-
for (;;)
829+
do
829830
{
830831
TupleTableSlot *slot;
831-
BufferHeapTupleTableSlot *bslot;
832832

833833
CHECK_FOR_INTERRUPTS();
834834

@@ -855,11 +855,9 @@ systable_inplace_update_begin(Relation relation,
855855
slot = scan->slot;
856856
Assert(TTS_IS_BUFFERTUPLE(slot));
857857
bslot = (BufferHeapTupleTableSlot *) slot;
858-
if (heap_inplace_lock(scan->heap_rel,
859-
bslot->base.tuple, bslot->buffer))
860-
break;
861-
systable_endscan(scan);
862-
};
858+
} while (!heap_inplace_lock(scan->heap_rel,
859+
bslot->base.tuple, bslot->buffer,
860+
(void (*) (void *)) systable_endscan, scan));
863861

864862
*oldtupcopy = heap_copytuple(oldtup);
865863
*state = scan;

src/include/access/heapam.h

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

339339
extern bool heap_inplace_lock(Relation relation,
340-
HeapTuple oldtup_ptr, Buffer buffer);
340+
HeapTuple oldtup_ptr, Buffer buffer,
341+
void (*release_callback) (void *), void *arg);
341342
extern void heap_inplace_update_and_unlock(Relation relation,
342343
HeapTuple oldtup, HeapTuple tuple,
343344
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