On Tue, Sep 15, 2020 at 2:04 PM Andres Freund <and...@anarazel.de> wrote: > > How is it possible? Because tuple which has a committed xmax and the > > xmax is older than the oldestXmin, should not come for freezing unless > > it is lock_only xid (because those tuples are already gone). > > There've been several cases of this in the past. A fairly easy way is a > corrupted relfrozenxid (of which there are many examples).
Hmm, so is the case you're worried about here the case where the freezing threshold is greater than the pruning threshold? i.e. The relfrozenxid has been updated to a value greater than the xmin we derive from the procarray? If that's not the case, then I don't see what problem there can be here. To reach heap_prepare_freeze_tuple the tuple has to survive pruning. If xmin < freezing-threshold and freezing-threshold < pruning-threshold and the tuple survived pruning, then xmin must be a committed transaction visible to everyone so setting xmin to FrozenTransactionId is fine. If xmax < freezing-threshold and freezing-threshold < pruning-threshold and the tuple survived pruning, xmax must be visible to everyone and can't be running so it must have aborted, so setting xmax to InvalidTransactionId is fine. On the other hand if, somehow, freezing-threshold > pruning-threshold, then freezing seems categorically unsafe. Doing so would change visibility decisions of transactions that are still running, or that were running at the time when we computed the pruning threshold. But the sanity checks in heap_prepare_freeze_tuple() seem like they would catch many such cases, but I'm not sure if they're all water-tight. It might be better to skip calling heap_prepare_freeze_tuple() altogether if the freezing threshold does not precede the pruning threshold. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company