mirror of
https://github.com/postgres/postgres.git
synced 2025-11-24 00:23:06 +03:00
Unpin buffer before inplace update waits for an XID to end.
Commit a07e03fd8f 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
This commit is contained in:
@@ -814,6 +814,7 @@ systable_inplace_update_begin(Relation relation,
|
||||
int retries = 0;
|
||||
SysScanDesc scan;
|
||||
HeapTuple oldtup;
|
||||
BufferHeapTupleTableSlot *bslot;
|
||||
|
||||
/*
|
||||
* For now, we don't allow parallel updates. Unlike a regular update,
|
||||
@@ -835,10 +836,9 @@ systable_inplace_update_begin(Relation relation,
|
||||
Assert(IsInplaceUpdateRelation(relation) || !IsSystemRelation(relation));
|
||||
|
||||
/* Loop for an exclusive-locked buffer of a non-updated tuple. */
|
||||
for (;;)
|
||||
do
|
||||
{
|
||||
TupleTableSlot *slot;
|
||||
BufferHeapTupleTableSlot *bslot;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
@@ -864,11 +864,9 @@ systable_inplace_update_begin(Relation relation,
|
||||
slot = scan->slot;
|
||||
Assert(TTS_IS_BUFFERTUPLE(slot));
|
||||
bslot = (BufferHeapTupleTableSlot *) slot;
|
||||
if (heap_inplace_lock(scan->heap_rel,
|
||||
bslot->base.tuple, bslot->buffer))
|
||||
break;
|
||||
systable_endscan(scan);
|
||||
};
|
||||
} while (!heap_inplace_lock(scan->heap_rel,
|
||||
bslot->base.tuple, bslot->buffer,
|
||||
(void (*) (void *)) systable_endscan, scan));
|
||||
|
||||
*oldtupcopy = heap_copytuple(oldtup);
|
||||
*state = scan;
|
||||
|
||||
Reference in New Issue
Block a user