By the way, I still wonder if there's any way for a new tuple to get inserted in the place where a HOT redirect would be pointing to, and have it be marked as Frozen, where the old redirect contains a non-invalid Xmax. I tried to think of a way for that to happen, but couldn't think of anything.
What I imagine is a sequence like this: 1. insert a tuple 2. HOT-update a tuple 3. prune the page, making lp 1 be a redirect (lp 2 is the new tuple) 4. start transaction 5. HOT-update the tuple again, creating HOT in lp 3 6. abort transaction (leaving aborted update in lp 3) 7. somehow remove tuple from lp 3, make slot available 8. new transaction comes along, inserts tuple in lp 3 9. somebody freezes tuple in lp3 (???) Then we follow the HOT chain, see that Xmin=2 in lp3 and conclude that the tuple is part of the chain because of an xid "match". Basically from step 7 onwards I don't think this is possible, but maybe I'm just blind. Maybe we can forestall the problem by checking whether the Xmax TransactionIdIsCurrentTransaction || TransactionIdDidCommit (or some variant thereof). This would be very slow but safer; and in 9.4 and up we'd only need to do it if the xmin value is actually FrozenXid which should be rare (only in pages upgraded from 9.3). -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- Sent via pgsql-hackers mailing list (firstname.lastname@example.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers