mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Fix data loss at inplace update after heap_update().
As previously-added tests demonstrated, heap_inplace_update() could instead update an unrelated tuple of the same catalog. It could lose the update. Losing relhasindex=t was a source of index corruption. Inplace-updating commands like VACUUM will now wait for heap_update() commands like GRANT TABLE and GRANT DATABASE. That isn't ideal, but a long-running GRANT already hurts VACUUM progress more just by keeping an XID running. The VACUUM will behave like a DELETE or UPDATE waiting for the uncommitted change. For implementation details, start at the systable_inplace_update_begin() header comment and README.tuplock. Back-patch to v12 (all supported versions). In back branches, retain a deprecated heap_inplace_update(), for extensions. Reported by Smolkin Grigory. Reviewed by Nitin Motiani, (in earlier versions) Heikki Linnakangas, and (in earlier versions) Alexander Lakhin. Discussion: https://postgr.es/m/CAMp+ueZQz3yDk7qg42hk6-9gxniYbp-=bG2mgqecErqR5gGGOA@mail.gmail.com
This commit is contained in:
@ -233,5 +233,14 @@ extern SysScanDesc systable_beginscan_ordered(Relation heapRelation,
|
||||
extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan,
|
||||
ScanDirection direction);
|
||||
extern void systable_endscan_ordered(SysScanDesc sysscan);
|
||||
extern void systable_inplace_update_begin(Relation relation,
|
||||
Oid indexId,
|
||||
bool indexOK,
|
||||
Snapshot snapshot,
|
||||
int nkeys, const ScanKeyData *key,
|
||||
HeapTuple *oldtupcopy,
|
||||
void **state);
|
||||
extern void systable_inplace_update_finish(void *state, HeapTuple tuple);
|
||||
extern void systable_inplace_update_cancel(void *state);
|
||||
|
||||
#endif /* GENAM_H */
|
||||
|
@ -337,7 +337,13 @@ extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
|
||||
bool follow_updates,
|
||||
Buffer *buffer, struct TM_FailureData *tmfd);
|
||||
|
||||
extern void heap_inplace_update(Relation relation, HeapTuple tuple);
|
||||
extern bool heap_inplace_lock(Relation relation,
|
||||
HeapTuple oldtup_ptr, Buffer buffer);
|
||||
extern void heap_inplace_update_and_unlock(Relation relation,
|
||||
HeapTuple oldtup, HeapTuple tuple,
|
||||
Buffer buffer);
|
||||
extern void heap_inplace_unlock(Relation relation,
|
||||
HeapTuple oldtup, Buffer buffer);
|
||||
extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple,
|
||||
const struct VacuumCutoffs *cutoffs,
|
||||
HeapPageFreeze *pagefrz,
|
||||
|
Reference in New Issue
Block a user