Cc: pgsql-hackers removed, as this mail contains a patch. Tom Lane wrote: > Alvaro Herrera <[EMAIL PROTECTED]> writes: > > Hannu Krossing asked me about his patch to ignore transactions running > > VACUUM LAZY in other vacuum transactions. I attach a version of the > > patch updated to the current sources. > > nonInVacuumXmin seems useless ... perhaps a vestige of some earlier > version of the computation?
Yup -- I checked that code and found out that nonInVacuumXmin can be taken out as it's not used anywhere. One upside of this is that taking it out means we can remove all diffs to GetSnapshotData. New patch attached; it's a bit smaller than the last one. I'm currently testing it. Since it appears there are no further objections, I intend to commit it. -- Alvaro Herrera http://www.CommandPrompt.com/ The PostgreSQL Company - Command Prompt, Inc.
Index: src/backend/access/transam/twophase.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/access/transam/twophase.c,v retrieving revision 1.21 diff -c -r1.21 twophase.c *** src/backend/access/transam/twophase.c 14 Jul 2006 14:52:17 -0000 1.21 --- src/backend/access/transam/twophase.c 24 Jul 2006 22:16:35 -0000 *************** *** 279,284 **** --- 279,285 ---- gxact->proc.pid = 0; gxact->proc.databaseId = databaseid; gxact->proc.roleId = owner; + gxact->proc.inVacuum = false; gxact->proc.lwWaiting = false; gxact->proc.lwExclusive = false; gxact->proc.lwWaitLink = NULL; Index: src/backend/access/transam/xact.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/access/transam/xact.c,v retrieving revision 1.224 diff -c -r1.224 xact.c *** src/backend/access/transam/xact.c 24 Jul 2006 16:32:44 -0000 1.224 --- src/backend/access/transam/xact.c 24 Jul 2006 22:16:35 -0000 *************** *** 1529,1534 **** --- 1529,1535 ---- LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->xid = InvalidTransactionId; MyProc->xmin = InvalidTransactionId; + MyProc->inVacuum = false; /* must be cleared with xid/xmin */ /* Clear the subtransaction-XID cache too while holding the lock */ MyProc->subxids.nxids = 0; *************** *** 1764,1769 **** --- 1765,1771 ---- LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->xid = InvalidTransactionId; MyProc->xmin = InvalidTransactionId; + MyProc->inVacuum = false; /* must be cleared with xid/xmin */ /* Clear the subtransaction-XID cache too while holding the lock */ MyProc->subxids.nxids = 0; *************** *** 1927,1932 **** --- 1929,1935 ---- LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->xid = InvalidTransactionId; MyProc->xmin = InvalidTransactionId; + MyProc->inVacuum = false; /* must be cleared with xid/xmin */ /* Clear the subtransaction-XID cache too while holding the lock */ MyProc->subxids.nxids = 0; Index: src/backend/access/transam/xlog.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/access/transam/xlog.c,v retrieving revision 1.244 diff -c -r1.244 xlog.c *** src/backend/access/transam/xlog.c 14 Jul 2006 14:52:17 -0000 1.244 --- src/backend/access/transam/xlog.c 24 Jul 2006 22:16:35 -0000 *************** *** 5413,5419 **** * StartupSUBTRANS hasn't been called yet. */ if (!InRecovery) ! TruncateSUBTRANS(GetOldestXmin(true)); if (!shutdown) ereport(DEBUG2, --- 5413,5419 ---- * StartupSUBTRANS hasn't been called yet. */ if (!InRecovery) ! TruncateSUBTRANS(GetOldestXmin(true, false)); if (!shutdown) ereport(DEBUG2, Index: src/backend/catalog/index.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/index.c,v retrieving revision 1.269 diff -c -r1.269 index.c *** src/backend/catalog/index.c 13 Jul 2006 16:49:13 -0000 1.269 --- src/backend/catalog/index.c 24 Jul 2006 22:16:35 -0000 *************** *** 1367,1373 **** else { snapshot = SnapshotAny; ! OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared); } scan = heap_beginscan(heapRelation, /* relation */ --- 1367,1374 ---- else { snapshot = SnapshotAny; ! /* okay to ignore lazy VACUUMs here */ ! OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared, true); } scan = heap_beginscan(heapRelation, /* relation */ Index: src/backend/commands/vacuum.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/vacuum.c,v retrieving revision 1.335 diff -c -r1.335 vacuum.c *** src/backend/commands/vacuum.c 14 Jul 2006 14:52:18 -0000 1.335 --- src/backend/commands/vacuum.c 24 Jul 2006 22:16:36 -0000 *************** *** 37,42 **** --- 37,43 ---- #include "postmaster/autovacuum.h" #include "storage/freespace.h" #include "storage/pmsignal.h" + #include "storage/proc.h" #include "storage/procarray.h" #include "utils/acl.h" #include "utils/builtins.h" *************** *** 589,595 **** { TransactionId limit; ! *oldestXmin = GetOldestXmin(sharedRel); Assert(TransactionIdIsNormal(*oldestXmin)); --- 590,602 ---- { TransactionId limit; ! /* ! * We can always ignore processes running lazy vacuum. This is because we ! * use these values only for deciding which tuples we must keep in the ! * tables. Since lazy vacuum doesn't write its xid to the table, it's ! * safe to ignore it. ! */ ! *oldestXmin = GetOldestXmin(sharedRel, true); Assert(TransactionIdIsNormal(*oldestXmin)); *************** *** 645,650 **** --- 652,662 ---- * pg_class would've been obsoleted. Of course, this only works for * fixed-size never-null columns, but these are. * + * Another reason for doing it this way is that when we are in a lazy + * VACUUM and have inVacuum set, we mustn't do any updates --- somebody + * vacuuming pg_class might think they could delete a tuple marked with + * xmin = our xid. + * * This routine is shared by full VACUUM, lazy VACUUM, and stand-alone * ANALYZE. */ *************** *** 996,1003 **** /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); ! /* functions in indexes may want a snapshot set */ ! ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); /* * Tell the cache replacement strategy that vacuum is causing all --- 1008,1042 ---- /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); ! ! if (vacstmt->full) ! { ! /* functions in indexes may want a snapshot set */ ! ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); ! } ! else ! { ! /* ! * During a lazy VACUUM we do not run any user-supplied functions, ! * and so it should be safe to not create a transaction snapshot. ! * ! * We can furthermore set the inVacuum flag, which lets other ! * concurrent VACUUMs know that they can ignore this one while ! * determining their OldestXmin. (The reason we don't set inVacuum ! * during a full VACUUM is exactly that we may have to run user- ! * defined functions for functional indexes, and we want to make ! * sure that if they use the snapshot set above, any tuples it ! * requires can't get removed from other tables. An index function ! * that depends on the contents of other tables is arguably broken, ! * but we won't break it here by violating transaction semantics.) ! * ! * Note: the inVacuum flag remains set until CommitTransaction or ! * AbortTransaction. We don't want to clear it until we reset ! * MyProc->xid/xmin, else OldestXmin might appear to go backwards, ! * which is probably Not Good. ! */ ! MyProc->inVacuum = true; ! } /* * Tell the cache replacement strategy that vacuum is causing all Index: src/backend/storage/ipc/procarray.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/ipc/procarray.c,v retrieving revision 1.14 diff -c -r1.14 procarray.c *** src/backend/storage/ipc/procarray.c 14 Jul 2006 14:52:22 -0000 1.14 --- src/backend/storage/ipc/procarray.c 24 Jul 2006 22:16:43 -0000 *************** *** 388,407 **** * If allDbs is TRUE then all backends are considered; if allDbs is FALSE * then only backends running in my own database are considered. * * This is used by VACUUM to decide which deleted tuples must be preserved * in a table. allDbs = TRUE is needed for shared relations, but allDbs = * FALSE is sufficient for non-shared relations, since only backends in my ! * own database could ever see the tuples in them. * * This is also used to determine where to truncate pg_subtrans. allDbs ! * must be TRUE for that case. * * Note: we include the currently running xids in the set of considered xids. * This ensures that if a just-started xact has not yet set its snapshot, * when it does set the snapshot it cannot set xmin less than what we compute. */ TransactionId ! GetOldestXmin(bool allDbs) { ProcArrayStruct *arrayP = procArray; TransactionId result; --- 388,411 ---- * If allDbs is TRUE then all backends are considered; if allDbs is FALSE * then only backends running in my own database are considered. * + * If ignoreVacuum is TRUE then backends with inVacuum set are ignored. + * * This is used by VACUUM to decide which deleted tuples must be preserved * in a table. allDbs = TRUE is needed for shared relations, but allDbs = * FALSE is sufficient for non-shared relations, since only backends in my ! * own database could ever see the tuples in them. Also, we can ignore ! * concurrently running lazy VACUUMs because (a) they must be working on other ! * tables, and (b) they don't need to do snapshot-based lookups. * * This is also used to determine where to truncate pg_subtrans. allDbs ! * must be TRUE for that case, and ignoreVacuum FALSE. * * Note: we include the currently running xids in the set of considered xids. * This ensures that if a just-started xact has not yet set its snapshot, * when it does set the snapshot it cannot set xmin less than what we compute. */ TransactionId ! GetOldestXmin(bool allDbs, bool ignoreVacuum) { ProcArrayStruct *arrayP = procArray; TransactionId result; *************** *** 425,430 **** --- 429,437 ---- { PGPROC *proc = arrayP->procs[index]; + if (ignoreVacuum && proc->inVacuum) + continue; + if (allDbs || proc->databaseId == MyDatabaseId) { /* Fetch xid just once - see GetNewTransactionId */ Index: src/backend/storage/lmgr/proc.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/proc.c,v retrieving revision 1.178 diff -c -r1.178 proc.c *** src/backend/storage/lmgr/proc.c 23 Jul 2006 23:08:46 -0000 1.178 --- src/backend/storage/lmgr/proc.c 24 Jul 2006 22:16:43 -0000 *************** *** 257,262 **** --- 257,263 ---- /* databaseId and roleId will be filled in later */ MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; + MyProc->inVacuum = false; MyProc->lwWaiting = false; MyProc->lwExclusive = false; MyProc->lwWaitLink = NULL; *************** *** 388,393 **** --- 389,395 ---- MyProc->xmin = InvalidTransactionId; MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; + MyProc->inVacuum = false; MyProc->lwWaiting = false; MyProc->lwExclusive = false; MyProc->lwWaitLink = NULL; Index: src/include/storage/proc.h =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/include/storage/proc.h,v retrieving revision 1.89 diff -c -r1.89 proc.h *** src/include/storage/proc.h 13 Jul 2006 16:49:20 -0000 1.89 --- src/include/storage/proc.h 24 Jul 2006 22:16:44 -0000 *************** *** 73,78 **** --- 73,80 ---- Oid databaseId; /* OID of database this backend is using */ Oid roleId; /* OID of role using this backend */ + bool inVacuum; /* true if current xact is a LAZY VACUUM */ + /* Info about LWLock the process is currently waiting for, if any. */ bool lwWaiting; /* true if waiting for an LW lock */ bool lwExclusive; /* true if waiting for exclusive access */ Index: src/include/storage/procarray.h =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/include/storage/procarray.h,v retrieving revision 1.9 diff -c -r1.9 procarray.h *** src/include/storage/procarray.h 19 Jun 2006 01:51:22 -0000 1.9 --- src/include/storage/procarray.h 11 Jul 2006 16:44:03 -0000 *************** *** 24,30 **** extern bool TransactionIdIsInProgress(TransactionId xid); extern bool TransactionIdIsActive(TransactionId xid); ! extern TransactionId GetOldestXmin(bool allDbs); extern PGPROC *BackendPidGetProc(int pid); extern int BackendXidGetPid(TransactionId xid); --- 24,30 ---- extern bool TransactionIdIsInProgress(TransactionId xid); extern bool TransactionIdIsActive(TransactionId xid); ! extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum); extern PGPROC *BackendPidGetProc(int pid); extern int BackendXidGetPid(TransactionId xid);
---------------------------(end of broadcast)--------------------------- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq