1
0
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:
Noah Misch
2024-10-29 09:39:55 -07:00
parent 502e7bf7f0
commit 30d47ec8c6
3 changed files with 14 additions and 11 deletions

View File

@@ -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;