Correct comments of "Fix data loss at inplace update after heap_update()".
authorNoah Misch <[email protected]>
Mon, 15 Dec 2025 20:19:49 +0000 (12:19 -0800)
committerNoah Misch <[email protected]>
Mon, 15 Dec 2025 20:19:49 +0000 (12:19 -0800)
This corrects commit a07e03fd8fa7daf4d1356f7cb501ffe784ea6257.

Reported-by: Paul A Jungwirth <[email protected]>
Reported-by: Surya Poondla <[email protected]>
Reviewed-by: Paul A Jungwirth <[email protected]>
Discussion: https://postgr.es/m/CA+renyWCW+_2QvXERBQ+mna6ANwAVXXmHKCA-WzL04bZRsjoBA@mail.gmail.com

src/backend/access/heap/heapam.c
src/backend/access/index/genam.c

index 9636bb53ddd8d45391535cbad4750ec523ffbae2..3be8fabd7fb99874d4b2f3a78f9bb0aa3e87e02c 100644 (file)
@@ -6349,10 +6349,13 @@ heap_abort_speculative(Relation relation, const ItemPointerData *tid)
  * Since this is intended for system catalogs and SERIALIZABLE doesn't cover
  * DDL, this doesn't guarantee any particular predicate locking.
  *
- * One could modify this to return true for tuples with delete in progress,
- * All inplace updaters take a lock that conflicts with DROP.  If explicit
- * "DELETE FROM pg_class" is in progress, we'll wait for it like we would an
- * update.
+ * heap_delete() is a rarer source of blocking transactions (xwait).  We'll
+ * wait for such a transaction just like for the normal heap_update() case.
+ * Normal concurrent DROP commands won't cause that, because all inplace
+ * updaters take some lock that conflicts with DROP.  An explicit SQL "DELETE
+ * FROM pg_class" can cause it.  By waiting, if the concurrent transaction
+ * executed both "DELETE FROM pg_class" and "INSERT INTO pg_class", our caller
+ * can find the successor tuple.
  *
  * Readers of inplace-updated fields expect changes to those fields are
  * durable.  For example, vac_truncate_clog() reads datfrozenxid from
index 707c25289cd74aebcde4671145f38ee3de43c7c4..b7f10a1aed0bb12e2cda6f94f302a84d61a7d18f 100644 (file)
@@ -781,10 +781,11 @@ systable_endscan_ordered(SysScanDesc sysscan)
  * systable_inplace_update_begin --- update a row "in place" (overwrite it)
  *
  * Overwriting violates both MVCC and transactional safety, so the uses of
- * this function in Postgres are extremely limited.  Nonetheless we find some
- * places to use it.  See README.tuplock section "Locking to write
- * inplace-updated tables" and later sections for expectations of readers and
- * writers of a table that gets inplace updates.  Standard flow:
+ * this function in Postgres are extremely limited.  This makes no effort to
+ * support updating cache key columns or other indexed columns.  Nonetheless
+ * we find some places to use it.  See README.tuplock section "Locking to
+ * write inplace-updated tables" and later sections for expectations of
+ * readers and writers of a table that gets inplace updates.  Standard flow:
  *
  * ... [any slow preparation not requiring oldtup] ...
  * systable_inplace_update_begin([...], &tup, &inplace_state);