Why we still see some reports of "could not access transaction status"

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: pgsql-hackers(at)postgreSQL(dot)org
Subject: Why we still see some reports of "could not access transaction status"
Date: 2004-10-13 16:18:08
Message-ID: 15292.1097684288@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Having seen a couple recent reports of "could not access status of
transaction" for old, not-obviously-corrupt transaction numbers, I went
looking to see if I could find a way that the system could truncate CLOG
before it's really marked all occurrences of old transaction numbers as
known-dead or known-good.

I found one.

The problem is that there are several places where a tqual.c routine is
called without checking to see if it changed the tuple's commit hint
bits, and without necessarily writing the page immediately after. One
example is the code path in heap_update where we decide that we can't
update the tuple because a concurrent transaction did so. If
HeapTupleSatisfiesUpdate had set the XMIN_COMMITTED or XMAX_COMMITTED
bits, those bits would remain set in the shared buffer, but *the buffer
would not get marked dirty*.

Before PG 7.2 this was not a bug, because the hint bits could always be
set again later. But now, consider this scenario: while the buffer
remains in memory, VACUUM passes over the table. It doesn't find any
changes needed in that page, so it doesn't write the page either. At
completion of the vacuum, we check whether we can truncate CLOG,
discover we can, and do so. At some later point, the in-memory buffer
is discarded, still without having been written. When next read in,
the page contains an un-hinted transaction status that could easily
point to a transaction before the new CLOG boundary. Ooops.

The odds of such a problem seem exceedingly small ... in other words,
just about right to explain the small numbers of reports we get.

I think what we ought to do to solve this problem permanently is to stop
making the callers of the HeapTupleSatisfiesFoo() routines responsible
for checking for hint bit updates. It would be a lot safer, and AFAICS
not noticeably less efficient, for those routines to call
SetBufferCommitInfoNeedsSave for themselves. This would require adding
to their parameter lists, because they aren't currently told which
buffer the tuple is in, but that's no big deal considering we get to
simplify the calling logic in all the places that are faithfully doing
the t_infomask update check.

Comments?

regards, tom lane

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2004-10-13 16:35:02 Re: Two-phase commit security restrictions
Previous Message Heikki Linnakangas 2004-10-13 15:13:20 Two-phase commit security restrictions