Re: problems with table corruption continued
| От | Tom Lane |
|---|---|
| Тема | Re: problems with table corruption continued |
| Дата | |
| Msg-id | 1499.1008782595@sss.pgh.pa.us обсуждение исходный текст |
| Ответ на | Re: problems with table corruption continued (Tom Lane <tgl@sss.pgh.pa.us>) |
| Список | pgsql-hackers |
Okay, I've applied the attached patch to tqual.c. This brings all the
variants of HeapTupleSatisfies up to speed: I have compared them
carefully and they now all make equivalent series of tests on the tuple
status (though they may interpret the results differently).
I decided that Hiroshi had a good point about testing
TransactionIdIsInProgress, so the code now does that before risking
a change to t_infomask, even in the VACUUM cases.
regards, tom lane
*** src/backend/utils/time/tqual.c.orig Mon Oct 29 15:31:08 2001
--- src/backend/utils/time/tqual.c Wed Dec 19 12:09:32 2001
***************
*** 31,37 **** /* * HeapTupleSatisfiesItself * True iff heap tuple is valid for "itself."
! * "{it}self" means valid as of everything that's happened * in the current transaction, _including_
thecurrent command. * * Note:
--- 31,37 ---- /* * HeapTupleSatisfiesItself * True iff heap tuple is valid for "itself."
! * "itself" means valid as of everything that's happened * in the current transaction, _including_ the
currentcommand. * * Note:
***************
*** 53,59 **** bool HeapTupleSatisfiesItself(HeapTupleHeader tuple) {
- if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID)
--- 53,58 ----
***************
*** 61,86 **** if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID; return false; } }
elseif (tuple->t_infomask & HEAP_MOVED_IN) {
! if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin)) {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false; } } else if
(TransactionIdIsCurrentTransactionId(tuple->t_xmin)) { if (tuple->t_infomask & HEAP_XMAX_INVALID)
/*xid invalid */ return true; if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
return true; return false; } else if (!TransactionIdDidCommit(tuple->t_xmin))
--- 60,102 ---- if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) return false;
+ if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
+ {
+ if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
+ {
+ tuple->t_infomask |= HEAP_XMIN_INVALID;
+ return false;
+ }
+ tuple->t_infomask |= HEAP_XMIN_COMMITTED; } } else if (tuple->t_infomask
&HEAP_MOVED_IN) {
! if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) {
! if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
! return false;
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! tuple->t_infomask |= HEAP_XMIN_COMMITTED;
! else
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false;
! } } } else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
{ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true;
+
+ Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
+ if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return true;
+ return false; } else if (!TransactionIdDidCommit(tuple->t_xmin))
***************
*** 89,97 **** tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return false;
}
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; }
! /* the tuple was inserted validly */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted
*/ return true;
--- 105,115 ---- tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return false;
}
! else
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; }
!
! /* by here, the inserting transaction has committed */ if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid
invalidor aborted */ return true;
***************
*** 117,123 **** return true; }
! /* by here, deleting transaction has committed */ tuple->t_infomask |= HEAP_XMAX_COMMITTED; if
(tuple->t_infomask& HEAP_MARKED_FOR_UPDATE)
--- 135,141 ---- return true; }
! /* xmax transaction committed */ tuple->t_infomask |= HEAP_XMAX_COMMITTED; if (tuple->t_infomask &
HEAP_MARKED_FOR_UPDATE)
***************
*** 177,194 **** if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID; return false; } }
elseif (tuple->t_infomask & HEAP_MOVED_IN) {
! if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin)) {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false; } } else if
(TransactionIdIsCurrentTransactionId(tuple->t_xmin))
--- 195,225 ---- if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) return false;
+ if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
+ {
+ if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
+ {
+ tuple->t_infomask |= HEAP_XMIN_INVALID;
+ return false;
+ }
+ tuple->t_infomask |= HEAP_XMIN_COMMITTED; } } else if (tuple->t_infomask
&HEAP_MOVED_IN) {
! if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) {
! if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
! return false;
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! tuple->t_infomask |= HEAP_XMIN_COMMITTED;
! else
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false;
! } } } else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
***************
*** 215,221 **** tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return false;
}
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; } /* by here, the inserting transaction has committed */
--- 246,253 ---- tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return false;
}
! else
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; } /* by here, the inserting transaction has committed
*/
***************
*** 257,348 **** } int
! HeapTupleSatisfiesUpdate(HeapTuple tuple) {
! HeapTupleHeader th = tuple->t_data; if (AMI_OVERRIDE) return HeapTupleMayBeUpdated;
! if (!(th->t_infomask & HEAP_XMIN_COMMITTED)) {
! if (th->t_infomask & HEAP_XMIN_INVALID) /* xid invalid or aborted */ return HeapTupleInvisible;
! if (th->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdDidCommit((TransactionId) th->t_cmin))
! {
! th->t_infomask |= HEAP_XMIN_INVALID; return HeapTupleInvisible; }
}
! else if (th->t_infomask & HEAP_MOVED_IN) {
! if (!TransactionIdDidCommit((TransactionId) th->t_cmin)) {
! th->t_infomask |= HEAP_XMIN_INVALID;
! return HeapTupleInvisible; } }
! else if (TransactionIdIsCurrentTransactionId(th->t_xmin)) {
! if (CommandIdGEScanCommandId(th->t_cmin)) return HeapTupleInvisible; /* inserted
afterscan * started */
! if (th->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return
HeapTupleMayBeUpdated;
! Assert(TransactionIdIsCurrentTransactionId(th->t_xmax));
! if (th->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated;
! if (CommandIdGEScanCommandId(th->t_cmax)) return HeapTupleSelfUpdated; /* updated
afterscan * started */ else return
HeapTupleInvisible; /* updated before scan * started */
}
! else if (!TransactionIdDidCommit(th->t_xmin)) {
! if (TransactionIdDidAbort(th->t_xmin))
! th->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return HeapTupleInvisible;
}
! th->t_infomask |= HEAP_XMIN_COMMITTED; } /* by here, the inserting transaction has committed */
! if (th->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return HeapTupleMayBeUpdated;
! if (th->t_infomask & HEAP_XMAX_COMMITTED) {
! if (th->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated; return
HeapTupleUpdated; /* updated by other */ }
! if (TransactionIdIsCurrentTransactionId(th->t_xmax)) {
! if (th->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated;
! if (CommandIdGEScanCommandId(th->t_cmax)) return HeapTupleSelfUpdated; /* updated after
scan * started */ else return HeapTupleInvisible;
/* updated before scan started */ }
! if (!TransactionIdDidCommit(th->t_xmax)) {
! if (TransactionIdDidAbort(th->t_xmax)) {
! th->t_infomask |= HEAP_XMAX_INVALID; /* aborted */ return HeapTupleMayBeUpdated;
} /* running xact */
--- 289,394 ---- } int
! HeapTupleSatisfiesUpdate(HeapTuple htuple) {
! HeapTupleHeader tuple = htuple->t_data; if (AMI_OVERRIDE) return HeapTupleMayBeUpdated;
! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) {
! if (tuple->t_infomask & HEAP_XMIN_INVALID) return HeapTupleInvisible;
! if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) return
HeapTupleInvisible;
+ if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
+ {
+ if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
+ {
+ tuple->t_infomask |= HEAP_XMIN_INVALID;
+ return HeapTupleInvisible;
+ }
+ tuple->t_infomask |= HEAP_XMIN_COMMITTED; } }
! else if (tuple->t_infomask & HEAP_MOVED_IN) {
! if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) {
! if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
! return HeapTupleInvisible;
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! tuple->t_infomask |= HEAP_XMIN_COMMITTED;
! else
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return HeapTupleInvisible;
! } } }
! else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin)) {
! if (CommandIdGEScanCommandId(tuple->t_cmin)) return HeapTupleInvisible; /*
insertedafter scan * started */
! if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return
HeapTupleMayBeUpdated;
! Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
! if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated;
! if (CommandIdGEScanCommandId(tuple->t_cmax)) return HeapTupleSelfUpdated; /* updated
afterscan * started */ else return
HeapTupleInvisible; /* updated before scan * started */
}
! else if (!TransactionIdDidCommit(tuple->t_xmin)) {
! if (TransactionIdDidAbort(tuple->t_xmin))
! tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return HeapTupleInvisible;
}
! else
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; } /* by here, the inserting transaction has committed
*/
! if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return
HeapTupleMayBeUpdated;
! if (tuple->t_infomask & HEAP_XMAX_COMMITTED) {
! if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated; return
HeapTupleUpdated; /* updated by other */ }
! if (TransactionIdIsCurrentTransactionId(tuple->t_xmax)) {
! if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated;
! if (CommandIdGEScanCommandId(tuple->t_cmax)) return HeapTupleSelfUpdated; /* updated after
scan * started */ else return HeapTupleInvisible;
/* updated before scan started */ }
! if (!TransactionIdDidCommit(tuple->t_xmax)) {
! if (TransactionIdDidAbort(tuple->t_xmax)) {
! tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */ return HeapTupleMayBeUpdated;
} /* running xact */
***************
*** 350,358 **** } /* xmax transaction committed */
! th->t_infomask |= HEAP_XMAX_COMMITTED;
! if (th->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated; return HeapTupleUpdated;
/* updated by other */
--- 396,404 ---- } /* xmax transaction committed */
! tuple->t_infomask |= HEAP_XMAX_COMMITTED;
! if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE) return HeapTupleMayBeUpdated; return
HeapTupleUpdated; /* updated by other */
***************
*** 374,396 **** if (tuple->t_infomask & HEAP_MOVED_OFF) {
- /*
- * HeapTupleSatisfiesDirty is used by unique btree-s and so
- * may be used while vacuuming.
- */ if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
returnfalse;
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin)) {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false; }
- tuple->t_infomask |= HEAP_XMIN_COMMITTED; } else if (tuple->t_infomask & HEAP_MOVED_IN)
{ if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) {
if (TransactionIdDidCommit((TransactionId) tuple->t_cmin)) tuple->t_infomask |=
HEAP_XMIN_COMMITTED; else
--- 420,443 ---- if (tuple->t_infomask & HEAP_MOVED_OFF) { if
(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_cmin)) return false;
! if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin)) {
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false;
! }
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; } } else if (tuple->t_infomask
&HEAP_MOVED_IN) { if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
{
+ if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
+ return false; if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
tuple->t_infomask |= HEAP_XMIN_COMMITTED; else
***************
*** 416,425 **** { if (TransactionIdDidAbort(tuple->t_xmin)) {
! tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return false; }
SnapshotDirty->xmin = tuple->t_xmin; return true; /* in insertion by other */ }
else
--- 463,473 ---- { if (TransactionIdDidAbort(tuple->t_xmin)) {
! tuple->t_infomask |= HEAP_XMIN_INVALID; return false; }
SnapshotDirty->xmin= tuple->t_xmin;
+ /* XXX shouldn't we fall through to look at xmax? */ return true; /* in insertion by
other*/ } else
***************
*** 474,479 ****
--- 522,528 ---- if (AMI_OVERRIDE) return true;
+ /* XXX this is horribly ugly: */ if (ReferentialIntegritySnapshotOverride) return
HeapTupleSatisfiesNow(tuple);
***************
*** 484,501 **** if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID; return false; } }
elseif (tuple->t_infomask & HEAP_MOVED_IN) {
! if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin)) {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false; } } else if
(TransactionIdIsCurrentTransactionId(tuple->t_xmin))
--- 533,563 ---- if (tuple->t_infomask & HEAP_MOVED_OFF) {
! if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) return false;
+ if (!TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
+ {
+ if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
+ {
+ tuple->t_infomask |= HEAP_XMIN_INVALID;
+ return false;
+ }
+ tuple->t_infomask |= HEAP_XMIN_COMMITTED; } } else if (tuple->t_infomask
&HEAP_MOVED_IN) {
! if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin)) {
! if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
! return false;
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! tuple->t_infomask |= HEAP_XMIN_COMMITTED;
! else
! {
! tuple->t_infomask |= HEAP_XMIN_INVALID;
! return false;
! } } } else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
***************
*** 519,528 **** else if (!TransactionIdDidCommit(tuple->t_xmin)) { if
(TransactionIdDidAbort(tuple->t_xmin))
! tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */ return false; }
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; } /*
--- 581,591 ---- else if (!TransactionIdDidCommit(tuple->t_xmin)) { if
(TransactionIdDidAbort(tuple->t_xmin))
! tuple->t_infomask |= HEAP_XMIN_INVALID; return false; }
! else
! tuple->t_infomask |= HEAP_XMIN_COMMITTED; } /*
***************
*** 623,646 **** return HEAPTUPLE_DEAD; else if (tuple->t_infomask & HEAP_MOVED_OFF) {
if (TransactionIdDidCommit((TransactionId) tuple->t_cmin)) { tuple->t_infomask |=
HEAP_XMIN_INVALID; return HEAPTUPLE_DEAD; }
- /* Assume we can only get here if previous VACUUM aborted, */
- /* ie, it couldn't still be in progress */ tuple->t_infomask |= HEAP_XMIN_COMMITTED;
} else if (tuple->t_infomask & HEAP_MOVED_IN) {
! if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin)) {
- /* Assume we can only get here if previous VACUUM aborted */ tuple->t_infomask |=
HEAP_XMIN_INVALID; return HEAPTUPLE_DEAD; }
- tuple->t_infomask |= HEAP_XMIN_COMMITTED; } else if
(TransactionIdIsInProgress(tuple->t_xmin)) return HEAPTUPLE_INSERT_IN_PROGRESS;
--- 686,715 ---- return HEAPTUPLE_DEAD; else if (tuple->t_infomask & HEAP_MOVED_OFF) {
+ if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
+ return HEAPTUPLE_DELETE_IN_PROGRESS;
+ if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
+ return HEAPTUPLE_DELETE_IN_PROGRESS; if (TransactionIdDidCommit((TransactionId)
tuple->t_cmin)) { tuple->t_infomask |= HEAP_XMIN_INVALID; return
HEAPTUPLE_DEAD; } tuple->t_infomask |= HEAP_XMIN_COMMITTED; } else if
(tuple->t_infomask& HEAP_MOVED_IN) {
! if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
! return HEAPTUPLE_INSERT_IN_PROGRESS;
! if (TransactionIdIsInProgress((TransactionId) tuple->t_cmin))
! return HEAPTUPLE_INSERT_IN_PROGRESS;
! if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
! tuple->t_infomask |= HEAP_XMIN_COMMITTED;
! else { tuple->t_infomask |= HEAP_XMIN_INVALID; return
HEAPTUPLE_DEAD; } } else if (TransactionIdIsInProgress(tuple->t_xmin)) return
HEAPTUPLE_INSERT_IN_PROGRESS;
***************
*** 671,676 ****
--- 740,751 ---- if (tuple->t_infomask & HEAP_XMAX_INVALID) return HEAPTUPLE_LIVE;
+ if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ {
+ /* "deleting" xact really only marked it for update */
+ return HEAPTUPLE_LIVE;
+ }
+ if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { if (TransactionIdIsInProgress(tuple->t_xmax))
***************
*** 698,709 **** /* * Deleter committed, but check special cases. */
-
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- {
- /* "deleting" xact really only marked it for update */
- return HEAPTUPLE_LIVE;
- } if (TransactionIdEquals(tuple->t_xmin, tuple->t_xmax)) {
--- 773,778 ----
В списке pgsql-hackers по дате отправления: