Re: 13dev failed assert: comparetup_index_btree(): ItemPointer values should never be equal

From: Peter Geoghegan <pg(at)bowt(dot)ie>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Justin Pryzby <pryzby(at)telsasoft(dot)com>, James Coleman <jtc331(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>, Tomas Vondra <tomas(dot)vondra(at)postgresql(dot)org>, Alexander Korotkov <a(dot)korotkov(at)postgrespro(dot)ru>
Subject: Re: 13dev failed assert: comparetup_index_btree(): ItemPointer values should never be equal
Date: 2020-07-28 20:26:10
Message-ID: CAH2-WzkjjCoq5Y4LeeHJcjYJVxGm3M3SAWZ0=6J8K1FPSC9K0w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, Jul 28, 2020 at 1:04 PM Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:
> No, I don't think so. It was designed for the case of unique key X
> being inserted immediately after a deletion of the same key. The
> deleted tuple is presumably not yet vacuumed-away, so the new tuple
> should have a different TID. In no case should we have multiple index
> tuples pointing at the same TID; that would imply that somebody failed
> to vacuuum away an old index entry before freeing up the heap TID.

It looks like one HOT chain. I think cases where the
visibility/HeapTupleSatisfiesVacuum() stuff somehow gets confused
could result in the same heap TID (which is actually the HOT chain's
root TID) getting indexed twice.

> Or, perhaps, REINDEX is somehow scanning the same TID twice, and
> generating indeed-duplicate index entries?

It's 100% clear that that's what happens from my rr recording (kind
of). A conditional breakpoint in _bt_build_callback() clearly shows
that it gets called twice for the same TID value (twice in immediate
succession). The first time it gets called in the
!HeapTupleIsHeapOnlyTuple() path, the second time in the
HeapTupleIsHeapOnlyTuple() path (i.e. the path that uses the
root_offsets array).

I notice that the root tuple of the hot chain is marked HEAP_COMBOCID
(and xmin == xmax for the HOT chain tuple). The xmin for the successor
(which matches xmin and xmax for root tuple) exactly matches the
REINDEX/crashing session's OldestXmin.

--
Peter Geoghegan

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message MBeena Emerson 2020-07-28 20:42:12 Re: recovering from "found xmin ... from before relfrozenxid ..."
Previous Message Tom Lane 2020-07-28 20:04:26 Re: 13dev failed assert: comparetup_index_btree(): ItemPointer values should never be equal