Question about heap_inplace_update and VACUUM behavior

I am currently exploring the PostgreSQL source code to better understand the internal storage and update mechanisms. While reviewing the heap access methods, I noticed the function heap_inplace_update() in the source code with the following comment:

/*
 * heap_inplace_update - deprecated
 *
 * This exists only to keep modules working in back branches. Affected
 * modules should migrate to systable_inplace_update_begin().
 */

From my understanding, PostgreSQL generally follows the MVCC model, where updates create a new tuple version rather than modifying the existing tuple in place.

This raised a few questions for me:

  1. Does PostgreSQL still support any form of in-place updates internally, or is this function strictly kept for backward compatibility?

  2. What types of system catalog operations (if any) rely on in-place updates through systable_inplace_update_begin()?

  3. Since in-place updates do not generate a new tuple version, how does VACUUM interact with such updates? Does it need to handle them differently compared to normal MVCC updates?

  4. Are there any performance or concurrency considerations that influenced the decision to deprecate heap_inplace_update in favor of the newer APIs?

I would greatly appreciate any clarification or references to relevant documentation or design discussions.

Thank you for your time and for the incredible work on PostgreSQL.

Dies ist ein deutschsprachiges Forum. Bitte in Zukunft Fragen in Deutsch stellen

heap_inplace_update() gibt es nicht mehr, es wird nur aus Kompatibilitätsgründen in alten Releases bewahrt. Die relevante Lektüre sind die Commit-Message und die zugehörige Diskussion.

Was „In-Place-Update” an sich anbelangt, empfehle ich die Lektüre von src/backend/access/heap/README.tuplock und der Funktionen IsInplaceUpdateRelation() und IsInplaceUpdateOid():

/*
 * IsInplaceUpdateRelation
 *      True iff core code performs inplace updates on the relation.
 *
 *      This is used for assertions and for making the executor follow the
 *      locking protocol described at README.tuplock section "Locking to write
 *      inplace-updated tables".  Extensions may inplace-update other heap
 *      tables, but concurrent SQL UPDATE on the same table may overwrite
 *      those modifications.
 *
 *      The executor can assume these are not partitions or partitioned and
 *      have no triggers.
 */
bool
IsInplaceUpdateRelation(Relation relation)
{
    return IsInplaceUpdateOid(RelationGetRelid(relation));
}

/*
 * IsInplaceUpdateOid
 *      Like the above, but takes an OID as argument.
 */
bool
IsInplaceUpdateOid(Oid relid)
{
    return (relid == RelationRelationId ||
            relid == DatabaseRelationId);
}

Es ist also nicht sehr verbreitet und hat sicher keine Auswirkungen auf die Performance.

Abgesehen davon, daß der Frager diese Antwort möglicherweise nicht lesen können wird, ist die Frage ziemlich breit gestellt, und es ist nicht klar, worauf die Frage hinaus will. Ich glaube zwischen den Zeilen lesen zu können: „Ich habe eine Extension geschrieben, die heap_inplace_update() verwendet, und jetzt finde ich plötzlich diesen Kommentar im Code. Hilfe! Was soll ich damit anfangen?” Aber ohne eine konkrete Frage kann ich keine konkrete Antwort geben.

Die Frage wurde auch auf der Postgres Mailing Liste gestellt, und da ist sie vermutlich auch besser aufgehoben: