mirror of
https://github.com/postgres/postgres.git
synced 2025-11-06 07:49:08 +03:00
Repair problems with VACUUM destroying t_ctid chains too soon, and with
insufficient paranoia in code that follows t_ctid links. (We must do both because even with VACUUM doing it properly, the intermediate state with a dangling t_ctid link is visible concurrently during lazy VACUUM, and could be seen afterwards if either type of VACUUM crashes partway through.) Also try to improve documentation about what's going on. Patch is a bit bulky because passing the XMAX information around required changing the APIs of some low-level heapam.c routines, but it's not conceptually very complicated. Per trouble report from Teodor and subsequent analysis. This needs to be back-patched, but I'll do that after 8.1 beta is out.
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.89 2005/05/19 21:35:47 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.90 2005/08/20 00:39:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -677,14 +677,15 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
|
||||
* However, we also include the effects of other xacts still in progress.
|
||||
*
|
||||
* Returns extra information in the global variable SnapshotDirty, namely
|
||||
* xids of concurrent xacts that affected the tuple. Also, the tuple's
|
||||
* t_ctid (forward link) is returned if it's being updated.
|
||||
* xids of concurrent xacts that affected the tuple. SnapshotDirty->xmin
|
||||
* is set to InvalidTransactionId if xmin is either committed good or
|
||||
* committed dead; or to xmin if that transaction is still in progress.
|
||||
* Similarly for SnapshotDirty->xmax.
|
||||
*/
|
||||
bool
|
||||
HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
|
||||
{
|
||||
SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
|
||||
ItemPointerSetInvalid(&(SnapshotDirty->tid));
|
||||
|
||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||
{
|
||||
@@ -781,7 +782,6 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
|
||||
{
|
||||
if (tuple->t_infomask & HEAP_IS_LOCKED)
|
||||
return true;
|
||||
SnapshotDirty->tid = tuple->t_ctid;
|
||||
return false; /* updated by other */
|
||||
}
|
||||
|
||||
@@ -824,7 +824,6 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
|
||||
|
||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||
SetBufferCommitInfoNeedsSave(buffer);
|
||||
SnapshotDirty->tid = tuple->t_ctid;
|
||||
return false; /* updated by other */
|
||||
}
|
||||
|
||||
@@ -1224,10 +1223,13 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
|
||||
HeapTupleHeaderGetXmax(tuple)))
|
||||
{
|
||||
/*
|
||||
* inserter also deleted it, so it was never visible to anyone
|
||||
* else
|
||||
* Inserter also deleted it, so it was never visible to anyone
|
||||
* else. However, we can only remove it early if it's not an
|
||||
* updated tuple; else its parent tuple is linking to it via t_ctid,
|
||||
* and this tuple mustn't go away before the parent does.
|
||||
*/
|
||||
return HEAPTUPLE_DEAD;
|
||||
if (!(tuple->t_infomask & HEAP_UPDATED))
|
||||
return HEAPTUPLE_DEAD;
|
||||
}
|
||||
|
||||
if (!TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin))
|
||||
|
||||
Reference in New Issue
Block a user