On Tue, Jul 28, 2020 at 1:04 PM Tom Lane <t...@sss.pgh.pa.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