Raise error when affecting tuple moved into different partition

Enterprise / PostgreSQL - Andres Freund [anarazel.de] - 7 April 2018 20:24 EDT

When an update moves a row between partitions (supported since 2f178441044b), our normal logic for following update chains in READ COMMITTED mode doesn't work anymore. Cross partition updates are modeled as an delete from the old and insert into the new partition. No ctid chain exists across partitions, and there's no convenient space to introduce that link.

Not throwing an error in a partitioned context when one would have been thrown without partitioning is obviously problematic. This commit introduces infrastructure to detect when a tuple has been moved, not just plainly deleted. That allows to throw an error when encountering a deletion that's actually a move, while attempting to following a ctid chain.

The row deleted as part of a cross partition update is marked by pointing it's t_ctid to an invalid block, instead of self as a normal update would. That was deemed to be the least invasive and most future proof way to represent the knowledge, given how few infomask bits are there to be recycled (there's also some locking issues with using infomask bits).

External code following ctid chains should be updated to check for moved tuples. The most likely consequence of not doing so is a missed error.

Author: Amul Sul, editorialized by me

f16241bef7 Raise error when affecting tuple moved into different partition.
src/backend/access/heap/heapam.c | 39 +++++-
src/backend/access/heap/pruneheap.c | 6 +
src/backend/access/heap/rewriteheap.c | 1 +
src/backend/commands/trigger.c | 5 +
src/backend/executor/execMain.c | 12 ++
src/backend/executor/execMerge.c | 3 +-
src/backend/executor/execReplication.c | 22 +++-
src/backend/executor/nodeLockRows.c | 5 +
src/backend/executor/nodeModifyTable.c | 27 +++-
src/include/access/heapam.h | 2 +-
src/include/access/heapam_xlog.h | 1 +
src/include/access/htup_details.h | 12 +-
src/include/executor/nodeModifyTable.h | 3 +-
src/include/storage/itemptr.h | 16 +++
src/test/isolation/expected/merge-update.out | 25 ++++
.../isolation/expected/partition-key-update-1.out | 119 ++++++++++++++++++
.../isolation/expected/partition-key-update-2.out | 29 +++++
.../isolation/expected/partition-key-update-3.out | 139 +++++++++++++++++++++
src/test/isolation/isolation_schedule | 3 +
src/test/isolation/specs/merge-update.spec | 3 +-
.../isolation/specs/partition-key-update-1.spec | 85 +++++++++++++
.../isolation/specs/partition-key-update-2.spec | 45 +++++++
.../isolation/specs/partition-key-update-3.spec | 44 +++++++
23 files changed, 624 insertions(+), 22 deletions(-)

Upstream: git.postgresql.org


  • Share