2323 *
2424 *
2525 * IDENTIFICATION
26- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.14 2006/07/14 14:52:22 momjian Exp $
26+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.15 2006/07/30 02:07:18 alvherre Exp $
2727 *
2828 *-------------------------------------------------------------------------
2929 */
@@ -388,20 +388,24 @@ TransactionIdIsActive(TransactionId xid)
388388 * If allDbs is TRUE then all backends are considered; if allDbs is FALSE
389389 * then only backends running in my own database are considered.
390390 *
391+ * If ignoreVacuum is TRUE then backends with inVacuum set are ignored.
392+ *
391393 * This is used by VACUUM to decide which deleted tuples must be preserved
392394 * in a table.allDbs = TRUE is needed for shared relations, but allDbs =
393395 * FALSE is sufficient for non-shared relations, since only backends in my
394- * own database could ever see the tuples in them.
396+ * own database could ever see the tuples in them. Also, we can ignore
397+ * concurrently running lazy VACUUMs because (a) they must be working on other
398+ * tables, and (b) they don't need to do snapshot-based lookups.
395399 *
396400 * This is also used to determine where to truncate pg_subtrans. allDbs
397- * must be TRUE for that case.
401+ * must be TRUE for that case, and ignoreVacuum FALSE .
398402 *
399403 * Note: we include the currently running xids in the set of considered xids.
400404 * This ensures that if a just-started xact has not yet set its snapshot,
401405 * when it does set the snapshot it cannot set xmin less than what we compute.
402406 */
403407TransactionId
404- GetOldestXmin (bool allDbs )
408+ GetOldestXmin (bool allDbs , bool ignoreVacuum )
405409{
406410ProcArrayStruct * arrayP = procArray ;
407411TransactionId result ;
@@ -425,15 +429,28 @@ GetOldestXmin(bool allDbs)
425429{
426430PGPROC * proc = arrayP -> procs [index ];
427431
432+ if (ignoreVacuum && proc -> inVacuum )
433+ continue ;
434+
428435if (allDbs || proc -> databaseId == MyDatabaseId )
429436{
430437/* Fetch xid just once - see GetNewTransactionId */
431438TransactionId xid = proc -> xid ;
432439
433440if (TransactionIdIsNormal (xid ))
434441{
442+ /* First consider the transaction own's Xid */
435443if (TransactionIdPrecedes (xid ,result ))
436444result = xid ;
445+
446+ /*
447+ * Also consider the transaction's Xmin, if set.
448+ *
449+ * Note that this Xmin may seem to be guaranteed to be always
450+ * lower than the transaction's Xid, but this is not so because
451+ * there is a time window on which the Xid is already assigned
452+ * but the Xmin has not being calculated yet.
453+ */
437454xid = proc -> xmin ;
438455if (TransactionIdIsNormal (xid ))
439456if (TransactionIdPrecedes (xid ,result ))
@@ -471,8 +488,8 @@ GetOldestXmin(bool allDbs)
471488 *RecentXmin: the xmin computed for the most recent snapshot. XIDs
472489 *older than this are known not running any more.
473490 *RecentGlobalXmin: the global xmin (oldest TransactionXmin across all
474- *running transactions).This is the same computation done by
475- *GetOldestXmin(TRUE ).
491+ *running transactions, except those running LAZY VACUUM). This is
492+ *the same computation done by GetOldestXmin(true, false ).
476493 *----------
477494 */
478495Snapshot
@@ -561,15 +578,17 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
561578
562579/*
563580 * Ignore my own proc (dealt with my xid above), procs not running a
564- * transaction, and xacts started since we read the next transaction
565- * ID.There's no need to store XIDs above what we got from
566- * ReadNewTransactionId, since we'll treat them as running anyway. We
567- * also assume that such xacts can't compute an xmin older than ours,
568- * so they needn't be considered in computing globalxmin.
581+ * transaction, xacts started since we read the next transaction
582+ * ID, and xacts executing LAZY VACUUM.There's no need to store XIDs
583+ * above what we got from ReadNewTransactionId, since we'll treat them
584+ * as running anyway. We also assume that such xacts can't compute an
585+ * xmin older than ours, so they needn't be considered in computing
586+ * globalxmin.
569587 */
570588if (proc == MyProc ||
571589!TransactionIdIsNormal (xid )||
572- TransactionIdFollowsOrEquals (xid ,xmax ))
590+ TransactionIdFollowsOrEquals (xid ,xmax )||
591+ proc -> inVacuum )
573592continue ;
574593
575594if (TransactionIdPrecedes (xid ,xmin ))