Re: pgsql: Fix traversal of half-frozen update chains

From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Peter Geoghegan <pg(at)bowt(dot)ie>
Cc: pgsql-committers <pgsql-committers(at)postgresql(dot)org>
Subject: Re: pgsql: Fix traversal of half-frozen update chains
Date: 2017-10-17 10:40:59
Message-ID: 20171017104059.sq76kgd42ld55npp@alvherre.pgsql
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-committers pgsql-hackers

Peter Geoghegan wrote:

> Wouldn't this last "if" test, to cover the pg_upgrade case, be better
> targeted by comparing *raw* xmin to FrozenTransactionId? You're using
> the potentially distinct xmin value returned by
> HeapTupleHeaderGetXmin() for the test here. I think we should be
> directly targeting tuples frozen on or before 9.4 (prior to
> pg_upgrade) instead.

I also realized we can stop checking (i.e. don't compare xmin to
frozenxid) if the XMIN_FROZEN bits are set -- because in that case the
tuple cannot possibly come from 9.3 frozen. So I think this should do
it.

/*
* HeapTupleUpdateXmaxMatchesXmin - verify update chain xmax/xmin lineage
*
* Given the new version of a tuple after some update, verify whether the
* given Xmax (corresponding to the previous version) matches the tuple's
* Xmin, taking into account that the Xmin might have been frozen after the
* update.
*/
bool
HeapTupleUpdateXmaxMatchesXmin(TransactionId xmax, HeapTupleHeader htup)
{
TransactionId rawxmin = HeapTupleHeaderGetRawXmin(htup);
TransactionId xmin = HeapTupleHeaderGetXmin(htup);

/*
* If the xmax of the old tuple is identical to the xmin of the new one,
* it's a match.
*/
if (TransactionIdEquals(xmax, xmin))
return true;

/*
* If the HEAP_XMIN_FROZEN flag is set, then we know it can only be a match
* if the Xmin before the freezing is identical to the Xmax -- we can skip
* the fuzzy pg_upgraded check below.
*/
if (HeapTupleHeaderXminFrozen(htup))
{
if (TransactionIdEquals(rawxmin, xmax))
return true;
else
return false;
}

/*
* When a tuple is frozen, the original Xmin is lost, but we know it's a
* committed transaction. So unless the Xmax is InvalidXid, we don't know
* for certain that there is a match, but there may be one; and we must
* return true so that a HOT chain that is half-frozen can be walked
* correctly.
*
* We no longer freeze tuples this way, but we must keep this in order to
* interpret pre-pg_upgrade pages correctly.
*/
if (TransactionIdEquals(rawxmin, FrozenTransactionId) &&
TransactionIdIsValid(xmax))
return true;

return false;
}

--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

In response to

Responses

Browse pgsql-committers by date

  From Date Subject
Next Message Tom Lane 2017-10-17 16:15:25 pgsql: Fix misparsing of non-newline-terminated pg_hba.conf files.
Previous Message Alvaro Herrera 2017-10-17 10:02:00 Re: [COMMITTERS] pgsql: Fix traversal of half-frozen update chains

Browse pgsql-hackers by date

  From Date Subject
Next Message Alvaro Herrera 2017-10-17 10:59:16 Re: SIGSEGV in BRIN autosummarize
Previous Message Alvaro Herrera 2017-10-17 10:02:00 Re: [COMMITTERS] pgsql: Fix traversal of half-frozen update chains