1 /*-------------------------------------------------------------------------
4 * POSTGRES "time qualification" code, ie, tuple visibility rules.
6 * NOTE: all the HeapTupleSatisfies routines will update the tuple's
7 * "hint" status bits if we see that the inserting or deleting transaction
8 * has now committed or aborted (and it is safe to set the hint bits).
9 * If the hint bits are changed, SetBufferCommitInfoNeedsSave is called on
10 * the passed-in buffer. The caller must hold not only a pin, but at least
11 * shared buffer content lock on the buffer containing the tuple.
13 * NOTE: must check TransactionIdIsInProgress (which looks in PGXACT array)
14 * before TransactionIdDidCommit/TransactionIdDidAbort (which look in
15 * pg_clog). Otherwise we have a race condition: we might decide that a
16 * just-committed transaction crashed, because none of the tests succeed.
17 * xact.c is careful to record commit/abort in pg_clog before it unsets
18 * MyPgXact->xid in PGXACT array. That fixes that problem, but it also
19 * means there is a window where TransactionIdIsInProgress and
20 * TransactionIdDidCommit will both return true. If we check only
21 * TransactionIdDidCommit, we could consider a tuple committed when a
22 * later GetSnapshotData call will still think the originating transaction
23 * is in progress, which leads to application-level inconsistency. The
24 * upshot is that we gotta check TransactionIdIsInProgress first in all
25 * code paths, except for a few cases where we are looking at
26 * subtransactions of our own main transaction and so there can't be any
29 * Summary of visibility functions:
31 * HeapTupleSatisfiesMVCC()
32 * visible to supplied snapshot, excludes current command
33 * HeapTupleSatisfiesNow()
34 * visible to instant snapshot, excludes current command
35 * HeapTupleSatisfiesUpdate()
36 * like HeapTupleSatisfiesNow(), but with user-supplied command
37 * counter and more complex result
38 * HeapTupleSatisfiesSelf()
39 * visible to instant snapshot and current command
40 * HeapTupleSatisfiesDirty()
41 * like HeapTupleSatisfiesSelf(), but includes open transactions
42 * HeapTupleSatisfiesVacuum()
43 * visible to any running transaction, used by VACUUM
44 * HeapTupleSatisfiesToast()
45 * visible unless part of interrupted vacuum, used for TOAST
46 * HeapTupleSatisfiesAny()
47 * all tuples are visible
49 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
50 * Portions Copyright (c) 1994, Regents of the University of California
53 * src/backend/utils/time/tqual.c
55 *-------------------------------------------------------------------------
60 #include "access/htup_details.h"
61 #include "access/multixact.h"
62 #include "access/subtrans.h"
63 #include "access/transam.h"
64 #include "access/xact.h"
65 #include "storage/bufmgr.h"
66 #include "storage/procarray.h"
67 #include "utils/tqual.h"
70 /* Static variables representing various special snapshot semantics */
71 SnapshotData SnapshotNowData = {HeapTupleSatisfiesNow};
72 SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf};
73 SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
74 SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast};
77 static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
83 * Set commit/abort hint bits on a tuple, if appropriate at this time.
85 * It is only safe to set a transaction-committed hint bit if we know the
86 * transaction's commit record has been flushed to disk, or if the table is
87 * temporary or unlogged and will be obliterated by a crash anyway. We
88 * cannot change the LSN of the page here because we may hold only a share
89 * lock on the buffer, so we can't use the LSN to interlock this; we have to
90 * just refrain from setting the hint bit until some future re-examination
93 * We can always set hint bits when marking a transaction aborted. (Some
94 * code in heapam.c relies on that!)
96 * Also, if we are cleaning up HEAP_MOVED_IN or HEAP_MOVED_OFF entries, then
97 * we can always set the hint bits, since pre-9.0 VACUUM FULL always used
98 * synchronous commits and didn't move tuples that weren't previously
99 * hinted. (This is not known by this subroutine, but is applied by its
100 * callers.) Note: old-style VACUUM FULL is gone, but we have to keep this
101 * module's support for MOVED_OFF/MOVED_IN flag bits for as long as we
102 * support in-place update from pre-9.0 databases.
104 * Normal commits may be asynchronous, so for those we need to get the LSN
105 * of the transaction and then check whether this is flushed.
107 * The caller should pass xid as the XID of the transaction to check, or
108 * InvalidTransactionId if no check is needed.
111 SetHintBits(HeapTupleHeader tuple, Buffer buffer,
112 uint16 infomask, TransactionId xid)
114 if (TransactionIdIsValid(xid))
116 /* NB: xid must be known committed here! */
117 XLogRecPtr commitLSN = TransactionIdGetCommitLSN(xid);
119 if (XLogNeedsFlush(commitLSN) && BufferIsPermanent(buffer))
120 return; /* not flushed yet, so don't set hint */
123 tuple->t_infomask |= infomask;
124 SetBufferCommitInfoNeedsSave(buffer);
128 * HeapTupleSetHintBits --- exported version of SetHintBits()
130 * This must be separate because of C99's brain-dead notions about how to
131 * implement inline functions.
134 HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
135 uint16 infomask, TransactionId xid)
137 SetHintBits(tuple, buffer, infomask, xid);
142 * HeapTupleSatisfiesSelf
143 * True iff heap tuple is valid "for itself".
145 * Here, we consider the effects of:
146 * all committed transactions (as of the current instant)
147 * previous commands of this transaction
148 * changes made by the current command
151 * Assumes heap tuple is valid.
153 * The satisfaction of "itself" requires the following:
155 * ((Xmin == my-transaction && the row was updated by the current transaction, and
156 * (Xmax is null it was not deleted
157 * [|| Xmax != my-transaction)]) [or it was deleted by another transaction]
160 * (Xmin is committed && the row was modified by a committed transaction, and
161 * (Xmax is null || the row has not been deleted, or
162 * (Xmax != my-transaction && the row was deleted by another transaction
163 * Xmax is not committed))) that has not been committed
166 HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
168 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
170 if (tuple->t_infomask & HEAP_XMIN_INVALID)
173 /* Used by pre-9.0 binary upgrades */
174 if (tuple->t_infomask & HEAP_MOVED_OFF)
176 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
178 if (TransactionIdIsCurrentTransactionId(xvac))
180 if (!TransactionIdIsInProgress(xvac))
182 if (TransactionIdDidCommit(xvac))
184 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
185 InvalidTransactionId);
188 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
189 InvalidTransactionId);
192 /* Used by pre-9.0 binary upgrades */
193 else if (tuple->t_infomask & HEAP_MOVED_IN)
195 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
197 if (!TransactionIdIsCurrentTransactionId(xvac))
199 if (TransactionIdIsInProgress(xvac))
201 if (TransactionIdDidCommit(xvac))
202 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
203 InvalidTransactionId);
206 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
207 InvalidTransactionId);
212 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
214 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
217 if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
220 Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
222 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
224 /* deleting subtransaction must have aborted */
225 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
226 InvalidTransactionId);
232 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
234 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
235 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
236 HeapTupleHeaderGetXmin(tuple));
239 /* it must have aborted or crashed */
240 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
241 InvalidTransactionId);
246 /* by here, the inserting transaction has committed */
248 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
251 if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
253 if (tuple->t_infomask & HEAP_IS_LOCKED)
255 return false; /* updated by other */
258 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
260 /* MultiXacts are currently only allowed to lock tuples */
261 Assert(tuple->t_infomask & HEAP_IS_LOCKED);
265 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
267 if (tuple->t_infomask & HEAP_IS_LOCKED)
272 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
275 if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
277 /* it must have aborted or crashed */
278 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
279 InvalidTransactionId);
283 /* xmax transaction committed */
285 if (tuple->t_infomask & HEAP_IS_LOCKED)
287 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
288 InvalidTransactionId);
292 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
293 HeapTupleHeaderGetXmax(tuple));
298 * HeapTupleSatisfiesNow
299 * True iff heap tuple is valid "now".
301 * Here, we consider the effects of:
302 * all committed transactions (as of the current instant)
303 * previous commands of this transaction
305 * Note we do _not_ include changes made by the current command. This
306 * solves the "Halloween problem" wherein an UPDATE might try to re-update
307 * its own output tuples, http://en.wikipedia.org/wiki/Halloween_Problem.
310 * Assumes heap tuple is valid.
312 * The satisfaction of "now" requires the following:
314 * ((Xmin == my-transaction && inserted by the current transaction
315 * Cmin < my-command && before this command, and
316 * (Xmax is null || the row has not been deleted, or
317 * (Xmax == my-transaction && it was deleted by the current transaction
318 * Cmax >= my-command))) but not before this command,
320 * (Xmin is committed && the row was inserted by a committed transaction, and
321 * (Xmax is null || the row has not been deleted, or
322 * (Xmax == my-transaction && the row is being deleted by this transaction
323 * Cmax >= my-command) || but it's not deleted "yet", or
324 * (Xmax != my-transaction && the row was deleted by another transaction
325 * Xmax is not committed)))) that has not been committed
329 HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
331 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
333 if (tuple->t_infomask & HEAP_XMIN_INVALID)
336 /* Used by pre-9.0 binary upgrades */
337 if (tuple->t_infomask & HEAP_MOVED_OFF)
339 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
341 if (TransactionIdIsCurrentTransactionId(xvac))
343 if (!TransactionIdIsInProgress(xvac))
345 if (TransactionIdDidCommit(xvac))
347 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
348 InvalidTransactionId);
351 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
352 InvalidTransactionId);
355 /* Used by pre-9.0 binary upgrades */
356 else if (tuple->t_infomask & HEAP_MOVED_IN)
358 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
360 if (!TransactionIdIsCurrentTransactionId(xvac))
362 if (TransactionIdIsInProgress(xvac))
364 if (TransactionIdDidCommit(xvac))
365 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
366 InvalidTransactionId);
369 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
370 InvalidTransactionId);
375 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
377 if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false))
378 return false; /* inserted after scan started */
380 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
383 if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
386 Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
388 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
390 /* deleting subtransaction must have aborted */
391 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
392 InvalidTransactionId);
396 if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
397 return true; /* deleted after scan started */
399 return false; /* deleted before scan started */
401 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
403 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
404 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
405 HeapTupleHeaderGetXmin(tuple));
408 /* it must have aborted or crashed */
409 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
410 InvalidTransactionId);
415 /* by here, the inserting transaction has committed */
417 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
420 if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
422 if (tuple->t_infomask & HEAP_IS_LOCKED)
427 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
429 /* MultiXacts are currently only allowed to lock tuples */
430 Assert(tuple->t_infomask & HEAP_IS_LOCKED);
434 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
436 if (tuple->t_infomask & HEAP_IS_LOCKED)
438 if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
439 return true; /* deleted after scan started */
441 return false; /* deleted before scan started */
444 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
447 if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
449 /* it must have aborted or crashed */
450 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
451 InvalidTransactionId);
455 /* xmax transaction committed */
457 if (tuple->t_infomask & HEAP_IS_LOCKED)
459 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
460 InvalidTransactionId);
464 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
465 HeapTupleHeaderGetXmax(tuple));
470 * HeapTupleSatisfiesAny
471 * Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
474 HeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
480 * HeapTupleSatisfiesToast
481 * True iff heap tuple is valid as a TOAST row.
483 * This is a simplified version that only checks for VACUUM moving conditions.
484 * It's appropriate for TOAST usage because TOAST really doesn't want to do
485 * its own time qual checks; if you can see the main table row that contains
486 * a TOAST reference, you should be able to see the TOASTed value. However,
487 * vacuuming a TOAST table is independent of the main table, and in case such
488 * a vacuum fails partway through, we'd better do this much checking.
490 * Among other things, this means you can't do UPDATEs of rows in a TOAST
494 HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot,
497 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
499 if (tuple->t_infomask & HEAP_XMIN_INVALID)
502 /* Used by pre-9.0 binary upgrades */
503 if (tuple->t_infomask & HEAP_MOVED_OFF)
505 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
507 if (TransactionIdIsCurrentTransactionId(xvac))
509 if (!TransactionIdIsInProgress(xvac))
511 if (TransactionIdDidCommit(xvac))
513 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
514 InvalidTransactionId);
517 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
518 InvalidTransactionId);
521 /* Used by pre-9.0 binary upgrades */
522 else if (tuple->t_infomask & HEAP_MOVED_IN)
524 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
526 if (!TransactionIdIsCurrentTransactionId(xvac))
528 if (TransactionIdIsInProgress(xvac))
530 if (TransactionIdDidCommit(xvac))
531 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
532 InvalidTransactionId);
535 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
536 InvalidTransactionId);
543 /* otherwise assume the tuple is valid for TOAST. */
548 * HeapTupleSatisfiesUpdate
550 * Same logic as HeapTupleSatisfiesNow, but returns a more detailed result
551 * code, since UPDATE needs to know more than "is it visible?". Also,
552 * tuples of my own xact are tested against the passed CommandId not
555 * The possible return codes are:
557 * HeapTupleInvisible: the tuple didn't exist at all when the scan started,
558 * e.g. it was created by a later CommandId.
560 * HeapTupleMayBeUpdated: The tuple is valid and visible, so it may be
563 * HeapTupleSelfUpdated: The tuple was updated by the current transaction,
564 * after the current scan started.
566 * HeapTupleUpdated: The tuple was updated by a committed transaction.
568 * HeapTupleBeingUpdated: The tuple is being updated by an in-progress
569 * transaction other than the current transaction. (Note: this includes
570 * the case where the tuple is share-locked by a MultiXact, even if the
571 * MultiXact includes the current transaction. Callers that want to
572 * distinguish that case must test for it themselves.)
575 HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
578 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
580 if (tuple->t_infomask & HEAP_XMIN_INVALID)
581 return HeapTupleInvisible;
583 /* Used by pre-9.0 binary upgrades */
584 if (tuple->t_infomask & HEAP_MOVED_OFF)
586 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
588 if (TransactionIdIsCurrentTransactionId(xvac))
589 return HeapTupleInvisible;
590 if (!TransactionIdIsInProgress(xvac))
592 if (TransactionIdDidCommit(xvac))
594 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
595 InvalidTransactionId);
596 return HeapTupleInvisible;
598 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
599 InvalidTransactionId);
602 /* Used by pre-9.0 binary upgrades */
603 else if (tuple->t_infomask & HEAP_MOVED_IN)
605 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
607 if (!TransactionIdIsCurrentTransactionId(xvac))
609 if (TransactionIdIsInProgress(xvac))
610 return HeapTupleInvisible;
611 if (TransactionIdDidCommit(xvac))
612 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
613 InvalidTransactionId);
616 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
617 InvalidTransactionId);
618 return HeapTupleInvisible;
622 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
624 if (HeapTupleHeaderGetCmin(tuple) >= curcid)
625 return HeapTupleInvisible; /* inserted after scan started */
627 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
628 return HeapTupleMayBeUpdated;
630 if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
631 return HeapTupleMayBeUpdated;
633 Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
635 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
637 /* deleting subtransaction must have aborted */
638 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
639 InvalidTransactionId);
640 return HeapTupleMayBeUpdated;
643 if (HeapTupleHeaderGetCmax(tuple) >= curcid)
644 return HeapTupleSelfUpdated; /* updated after scan started */
646 return HeapTupleInvisible; /* updated before scan started */
648 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
649 return HeapTupleInvisible;
650 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
651 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
652 HeapTupleHeaderGetXmin(tuple));
655 /* it must have aborted or crashed */
656 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
657 InvalidTransactionId);
658 return HeapTupleInvisible;
662 /* by here, the inserting transaction has committed */
664 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
665 return HeapTupleMayBeUpdated;
667 if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
669 if (tuple->t_infomask & HEAP_IS_LOCKED)
670 return HeapTupleMayBeUpdated;
671 return HeapTupleUpdated; /* updated by other */
674 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
676 /* MultiXacts are currently only allowed to lock tuples */
677 Assert(tuple->t_infomask & HEAP_IS_LOCKED);
679 if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))
680 return HeapTupleBeingUpdated;
681 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
682 InvalidTransactionId);
683 return HeapTupleMayBeUpdated;
686 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
688 if (tuple->t_infomask & HEAP_IS_LOCKED)
689 return HeapTupleMayBeUpdated;
690 if (HeapTupleHeaderGetCmax(tuple) >= curcid)
691 return HeapTupleSelfUpdated; /* updated after scan started */
693 return HeapTupleInvisible; /* updated before scan started */
696 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
697 return HeapTupleBeingUpdated;
699 if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
701 /* it must have aborted or crashed */
702 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
703 InvalidTransactionId);
704 return HeapTupleMayBeUpdated;
707 /* xmax transaction committed */
709 if (tuple->t_infomask & HEAP_IS_LOCKED)
711 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
712 InvalidTransactionId);
713 return HeapTupleMayBeUpdated;
716 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
717 HeapTupleHeaderGetXmax(tuple));
718 return HeapTupleUpdated; /* updated by other */
722 * HeapTupleSatisfiesDirty
723 * True iff heap tuple is valid including effects of open transactions.
725 * Here, we consider the effects of:
726 * all committed and in-progress transactions (as of the current instant)
727 * previous commands of this transaction
728 * changes made by the current command
730 * This is essentially like HeapTupleSatisfiesSelf as far as effects of
731 * the current transaction and committed/aborted xacts are concerned.
732 * However, we also include the effects of other xacts still in progress.
734 * A special hack is that the passed-in snapshot struct is used as an
735 * output argument to return the xids of concurrent xacts that affected the
736 * tuple. snapshot->xmin is set to the tuple's xmin if that is another
737 * transaction that's still in progress; or to InvalidTransactionId if the
738 * tuple's xmin is committed good, committed dead, or my own xact. Similarly
739 * for snapshot->xmax and the tuple's xmax.
742 HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot,
745 snapshot->xmin = snapshot->xmax = InvalidTransactionId;
747 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
749 if (tuple->t_infomask & HEAP_XMIN_INVALID)
752 /* Used by pre-9.0 binary upgrades */
753 if (tuple->t_infomask & HEAP_MOVED_OFF)
755 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
757 if (TransactionIdIsCurrentTransactionId(xvac))
759 if (!TransactionIdIsInProgress(xvac))
761 if (TransactionIdDidCommit(xvac))
763 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
764 InvalidTransactionId);
767 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
768 InvalidTransactionId);
771 /* Used by pre-9.0 binary upgrades */
772 else if (tuple->t_infomask & HEAP_MOVED_IN)
774 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
776 if (!TransactionIdIsCurrentTransactionId(xvac))
778 if (TransactionIdIsInProgress(xvac))
780 if (TransactionIdDidCommit(xvac))
781 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
782 InvalidTransactionId);
785 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
786 InvalidTransactionId);
791 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
793 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
796 if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
799 Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
801 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
803 /* deleting subtransaction must have aborted */
804 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
805 InvalidTransactionId);
811 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
813 snapshot->xmin = HeapTupleHeaderGetXmin(tuple);
814 /* XXX shouldn't we fall through to look at xmax? */
815 return true; /* in insertion by other */
817 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
818 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
819 HeapTupleHeaderGetXmin(tuple));
822 /* it must have aborted or crashed */
823 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
824 InvalidTransactionId);
829 /* by here, the inserting transaction has committed */
831 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
834 if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
836 if (tuple->t_infomask & HEAP_IS_LOCKED)
838 return false; /* updated by other */
841 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
843 /* MultiXacts are currently only allowed to lock tuples */
844 Assert(tuple->t_infomask & HEAP_IS_LOCKED);
848 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
850 if (tuple->t_infomask & HEAP_IS_LOCKED)
855 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
857 snapshot->xmax = HeapTupleHeaderGetXmax(tuple);
861 if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
863 /* it must have aborted or crashed */
864 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
865 InvalidTransactionId);
869 /* xmax transaction committed */
871 if (tuple->t_infomask & HEAP_IS_LOCKED)
873 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
874 InvalidTransactionId);
878 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
879 HeapTupleHeaderGetXmax(tuple));
880 return false; /* updated by other */
884 * HeapTupleSatisfiesMVCC
885 * True iff heap tuple is valid for the given MVCC snapshot.
887 * Here, we consider the effects of:
888 * all transactions committed as of the time of the given snapshot
889 * previous commands of this transaction
891 * Does _not_ include:
892 * transactions shown as in-progress by the snapshot
893 * transactions started after the snapshot was taken
894 * changes made by the current command
896 * This is the same as HeapTupleSatisfiesNow, except that transactions that
897 * were in progress or as yet unstarted when the snapshot was taken will
898 * be treated as uncommitted, even if they have committed by now.
900 * (Notice, however, that the tuple status hint bits will be updated on the
901 * basis of the true state of the transaction, even if we then pretend we
905 HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot,
908 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
910 if (tuple->t_infomask & HEAP_XMIN_INVALID)
913 /* Used by pre-9.0 binary upgrades */
914 if (tuple->t_infomask & HEAP_MOVED_OFF)
916 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
918 if (TransactionIdIsCurrentTransactionId(xvac))
920 if (!TransactionIdIsInProgress(xvac))
922 if (TransactionIdDidCommit(xvac))
924 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
925 InvalidTransactionId);
928 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
929 InvalidTransactionId);
932 /* Used by pre-9.0 binary upgrades */
933 else if (tuple->t_infomask & HEAP_MOVED_IN)
935 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
937 if (!TransactionIdIsCurrentTransactionId(xvac))
939 if (TransactionIdIsInProgress(xvac))
941 if (TransactionIdDidCommit(xvac))
942 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
943 InvalidTransactionId);
946 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
947 InvalidTransactionId);
952 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
954 if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
955 return false; /* inserted after scan started */
957 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
960 if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
963 Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
965 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
967 /* deleting subtransaction must have aborted */
968 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
969 InvalidTransactionId);
973 if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
974 return true; /* deleted after scan started */
976 return false; /* deleted before scan started */
978 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
980 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
981 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
982 HeapTupleHeaderGetXmin(tuple));
985 /* it must have aborted or crashed */
986 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
987 InvalidTransactionId);
993 * By here, the inserting transaction has committed - have to check
996 if (XidInMVCCSnapshot(HeapTupleHeaderGetXmin(tuple), snapshot))
997 return false; /* treat as still in progress */
999 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
1002 if (tuple->t_infomask & HEAP_IS_LOCKED)
1005 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1007 /* MultiXacts are currently only allowed to lock tuples */
1008 Assert(tuple->t_infomask & HEAP_IS_LOCKED);
1012 if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1014 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
1016 if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1017 return true; /* deleted after scan started */
1019 return false; /* deleted before scan started */
1022 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
1025 if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
1027 /* it must have aborted or crashed */
1028 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1029 InvalidTransactionId);
1033 /* xmax transaction committed */
1034 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1035 HeapTupleHeaderGetXmax(tuple));
1039 * OK, the deleting transaction committed too ... but when?
1041 if (XidInMVCCSnapshot(HeapTupleHeaderGetXmax(tuple), snapshot))
1042 return true; /* treat as still in progress */
1049 * HeapTupleSatisfiesVacuum
1051 * Determine the status of tuples for VACUUM purposes. Here, what
1052 * we mainly want to know is if a tuple is potentially visible to *any*
1053 * running transaction. If so, it can't be removed yet by VACUUM.
1055 * OldestXmin is a cutoff XID (obtained from GetOldestXmin()). Tuples
1056 * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
1057 * still be visible to some open transaction, so we can't remove them,
1058 * even if we see that the deleting transaction has committed.
1061 HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
1065 * Has inserting transaction committed?
1067 * If the inserting transaction aborted, then the tuple was never visible
1068 * to any other transaction, so we can delete it immediately.
1070 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
1072 if (tuple->t_infomask & HEAP_XMIN_INVALID)
1073 return HEAPTUPLE_DEAD;
1074 /* Used by pre-9.0 binary upgrades */
1075 else if (tuple->t_infomask & HEAP_MOVED_OFF)
1077 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1079 if (TransactionIdIsCurrentTransactionId(xvac))
1080 return HEAPTUPLE_DELETE_IN_PROGRESS;
1081 if (TransactionIdIsInProgress(xvac))
1082 return HEAPTUPLE_DELETE_IN_PROGRESS;
1083 if (TransactionIdDidCommit(xvac))
1085 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1086 InvalidTransactionId);
1087 return HEAPTUPLE_DEAD;
1089 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1090 InvalidTransactionId);
1092 /* Used by pre-9.0 binary upgrades */
1093 else if (tuple->t_infomask & HEAP_MOVED_IN)
1095 TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1097 if (TransactionIdIsCurrentTransactionId(xvac))
1098 return HEAPTUPLE_INSERT_IN_PROGRESS;
1099 if (TransactionIdIsInProgress(xvac))
1100 return HEAPTUPLE_INSERT_IN_PROGRESS;
1101 if (TransactionIdDidCommit(xvac))
1102 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1103 InvalidTransactionId);
1106 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1107 InvalidTransactionId);
1108 return HEAPTUPLE_DEAD;
1111 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
1113 if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1114 return HEAPTUPLE_INSERT_IN_PROGRESS;
1115 if (tuple->t_infomask & HEAP_IS_LOCKED)
1116 return HEAPTUPLE_INSERT_IN_PROGRESS;
1117 /* inserted and then deleted by same xact */
1118 return HEAPTUPLE_DELETE_IN_PROGRESS;
1120 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
1121 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1122 HeapTupleHeaderGetXmin(tuple));
1126 * Not in Progress, Not Committed, so either Aborted or crashed
1128 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1129 InvalidTransactionId);
1130 return HEAPTUPLE_DEAD;
1134 * At this point the xmin is known committed, but we might not have
1135 * been able to set the hint bit yet; so we can no longer Assert that
1141 * Okay, the inserter committed, so it was good at some point. Now what
1142 * about the deleting transaction?
1144 if (tuple->t_infomask & HEAP_XMAX_INVALID)
1145 return HEAPTUPLE_LIVE;
1147 if (tuple->t_infomask & HEAP_IS_LOCKED)
1150 * "Deleting" xact really only locked it, so the tuple is live in any
1151 * case. However, we should make sure that either XMAX_COMMITTED or
1152 * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
1153 * examining the tuple for future xacts. Also, marking dead
1154 * MultiXacts as invalid here provides defense against MultiXactId
1155 * wraparound (see also comments in heap_freeze_tuple()).
1157 if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1159 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1161 if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))
1162 return HEAPTUPLE_LIVE;
1166 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
1167 return HEAPTUPLE_LIVE;
1171 * We don't really care whether xmax did commit, abort or crash.
1172 * We know that xmax did lock the tuple, but it did not and will
1173 * never actually update it.
1175 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1176 InvalidTransactionId);
1178 return HEAPTUPLE_LIVE;
1181 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1183 /* MultiXacts are currently only allowed to lock tuples */
1184 Assert(tuple->t_infomask & HEAP_IS_LOCKED);
1185 return HEAPTUPLE_LIVE;
1188 if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1190 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
1191 return HEAPTUPLE_DELETE_IN_PROGRESS;
1192 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
1193 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1194 HeapTupleHeaderGetXmax(tuple));
1198 * Not in Progress, Not Committed, so either Aborted or crashed
1200 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1201 InvalidTransactionId);
1202 return HEAPTUPLE_LIVE;
1206 * At this point the xmax is known committed, but we might not have
1207 * been able to set the hint bit yet; so we can no longer Assert that
1213 * Deleter committed, but perhaps it was recent enough that some open
1214 * transactions could still see the tuple.
1216 if (!TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin))
1217 return HEAPTUPLE_RECENTLY_DEAD;
1219 /* Otherwise, it's dead and removable */
1220 return HEAPTUPLE_DEAD;
1224 * HeapTupleIsSurelyDead
1226 * Determine whether a tuple is surely dead. We sometimes use this
1227 * in lieu of HeapTupleSatisifesVacuum when the tuple has just been
1228 * tested by HeapTupleSatisfiesMVCC and, therefore, any hint bits that
1229 * can be set should already be set. We assume that if no hint bits
1230 * either for xmin or xmax, the transaction is still running. This is
1231 * therefore faster than HeapTupleSatisfiesVacuum, because we don't
1232 * consult CLOG (and also because we don't need to give an exact answer,
1233 * just whether or not the tuple is surely dead).
1236 HeapTupleIsSurelyDead(HeapTupleHeader tuple, TransactionId OldestXmin)
1239 * If the inserting transaction is marked invalid, then it aborted, and
1240 * the tuple is definitely dead. If it's marked neither committed nor
1241 * invalid, then we assume it's still alive (since the presumption is that
1242 * all relevant hint bits were just set moments ago).
1244 if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
1245 return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false;
1248 * If the inserting transaction committed, but any deleting transaction
1249 * aborted, the tuple is still alive. Likewise, if XMAX is a lock rather
1250 * than a delete, the tuple is still alive.
1252 if (tuple->t_infomask &
1253 (HEAP_XMAX_INVALID | HEAP_IS_LOCKED | HEAP_XMAX_IS_MULTI))
1256 /* If deleter isn't known to have committed, assume it's still running. */
1257 if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1260 /* Deleter committed, so tuple is dead if the XID is old enough. */
1261 return TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin);
1266 * Is the given XID still-in-progress according to the snapshot?
1268 * Note: GetSnapshotData never stores either top xid or subxids of our own
1269 * backend into a snapshot, so these xids will not be reported as "running"
1270 * by this function. This is OK for current uses, because we actually only
1271 * apply this for known-committed XIDs.
1274 XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
1279 * Make a quick range check to eliminate most XIDs without looking at the
1280 * xip arrays. Note that this is OK even if we convert a subxact XID to
1281 * its parent below, because a subxact with XID < xmin has surely also got
1282 * a parent with XID < xmin, while one with XID >= xmax must belong to a
1283 * parent that was not yet committed at the time of this snapshot.
1286 /* Any xid < xmin is not in-progress */
1287 if (TransactionIdPrecedes(xid, snapshot->xmin))
1289 /* Any xid >= xmax is in-progress */
1290 if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1294 * Snapshot information is stored slightly differently in snapshots taken
1297 if (!snapshot->takenDuringRecovery)
1300 * If the snapshot contains full subxact data, the fastest way to
1301 * check things is just to compare the given XID against both subxact
1302 * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1303 * use pg_subtrans to convert a subxact XID to its parent XID, but
1304 * then we need only look at top-level XIDs not subxacts.
1306 if (!snapshot->suboverflowed)
1308 /* full data, so search subxip */
1311 for (j = 0; j < snapshot->subxcnt; j++)
1313 if (TransactionIdEquals(xid, snapshot->subxip[j]))
1317 /* not there, fall through to search xip[] */
1321 /* overflowed, so convert xid to top-level */
1322 xid = SubTransGetTopmostTransaction(xid);
1325 * If xid was indeed a subxact, we might now have an xid < xmin,
1326 * so recheck to avoid an array scan. No point in rechecking
1329 if (TransactionIdPrecedes(xid, snapshot->xmin))
1333 for (i = 0; i < snapshot->xcnt; i++)
1335 if (TransactionIdEquals(xid, snapshot->xip[i]))
1344 * In recovery we store all xids in the subxact array because it is by
1345 * far the bigger array, and we mostly don't know which xids are
1346 * top-level and which are subxacts. The xip array is empty.
1348 * We start by searching subtrans, if we overflowed.
1350 if (snapshot->suboverflowed)
1352 /* overflowed, so convert xid to top-level */
1353 xid = SubTransGetTopmostTransaction(xid);
1356 * If xid was indeed a subxact, we might now have an xid < xmin,
1357 * so recheck to avoid an array scan. No point in rechecking
1360 if (TransactionIdPrecedes(xid, snapshot->xmin))
1365 * We now have either a top-level xid higher than xmin or an
1366 * indeterminate xid. We don't know whether it's top level or subxact
1367 * but it doesn't matter. If it's present, the xid is visible.
1369 for (j = 0; j < snapshot->subxcnt; j++)
1371 if (TransactionIdEquals(xid, snapshot->subxip[j]))