On 14.06.2024 10:45, Anton A. Melnikov wrote:
The src/backend/access/heap/README.tuplock says about HEAP_XMAX_INVALID bit that "Any tuple with this bit set does not have a valid value stored in XMAX."Found that FreezeMultiXactId() tries to process such an invalid multi xmax and may looks for an update xid in the pg_multixact for it. Maybe not do this work in FreezeMultiXactId() and exit immediately if the bit HEAP_XMAX_INVALID was already set?
Seems it is important to save the check that multi xmax is not behind relminmxid. So saved it and correct README.tuplock accordingly. Would be glad if someone take a look at the patch attached. With the best regards, -- Anton A. Melnikov Postgres Professional: http://www.postgrespro.com The Russian Postgres Company
From 7608078bddf35904427cb1c04497ab0c98e9d111 Mon Sep 17 00:00:00 2001 From: "Anton A. Melnikov" <a.melni...@postgrespro.ru> Date: Fri, 14 Jun 2024 10:42:55 +0300 Subject: [PATCH] Don't process multi xmax in the FreezeMultiXactId() if the HEAP_XMAX_INVALID bit was already set. --- src/backend/access/heap/README.tuplock | 1 + src/backend/access/heap/heapam.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/backend/access/heap/README.tuplock b/src/backend/access/heap/README.tuplock index 6441e8baf0..e198942647 100644 --- a/src/backend/access/heap/README.tuplock +++ b/src/backend/access/heap/README.tuplock @@ -124,6 +124,7 @@ The following infomask bits are applicable: - HEAP_XMAX_INVALID Any tuple with this bit set does not have a valid value stored in XMAX. + Although if it's a multi xmax it must follow relminmxid. - HEAP_XMAX_IS_MULTI This bit is set if the tuple's Xmax is a MultiXactId (as opposed to a diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 82bb9cb33b..d1cba6970d 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6227,6 +6227,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("found multixact %u from before relminmxid %u", multi, cutoffs->relminmxid))); + else if (MultiXactIdIsValid(multi) && + (t_infomask & HEAP_XMAX_INVALID)) + { + /* Xmax is already marked as invalid */ + *flags |= FRM_INVALIDATE_XMAX; + pagefrz->freeze_required = true; + return InvalidTransactionId; + } else if (MultiXactIdPrecedes(multi, cutoffs->OldestMxact)) { TransactionId update_xact; -- 2.45.2