Ühel kenal päeval, K, 2005-12-21 kell 09:50, kirjutas Hannu Krosing:
> Ühel kenal päeval, T, 2005-12-20 kell 17:18, kirjutas Tom Lane:
> > =?ISO-8859-1?Q?Hans-J=FCrgen_Sch=F6nig?= <[EMAIL PROTECTED]> writes:
> > > i was just wondering about the status of hannu's concurrent vacuum patch.
> > > are there any plans to integrate this
> >
> > I still don't trust it (assuming that you're thinking of the same patch
> > I am).
>
> What could I do to increase your trust in it ?
>
> Could you think of any specific case it could break ? Or any specific
> tests to check for it ?
>
> I attach the version of the patch for 8.1.0 for anyone interested in
> checking it.
It was pointed out to me that I did'nt.
So here it is:
---------------
Hannu
Index: src/backend/access/transam/twophase.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/twophase.c,v
retrieving revision 1.16
diff -c -r1.16 twophase.c
*** src/backend/access/transam/twophase.c 29 Oct 2005 00:31:50 -0000 1.16
--- src/backend/access/transam/twophase.c 21 Dec 2005 23:09:31 -0000
***************
*** 279,284 ****
--- 279,286 ----
gxact->proc.pid = 0;
gxact->proc.databaseId = databaseid;
gxact->proc.roleId = owner;
+ gxact->proc.inVacuum = false;
+ gxact->proc.nonInVacuumXmin = InvalidTransactionId;
gxact->proc.lwWaiting = false;
gxact->proc.lwExclusive = false;
gxact->proc.lwWaitLink = NULL;
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.215
diff -c -r1.215 xact.c
*** src/backend/access/transam/xact.c 15 Oct 2005 02:49:09 -0000 1.215
--- src/backend/access/transam/xact.c 21 Dec 2005 23:09:32 -0000
***************
*** 1507,1512 ****
--- 1507,1514 ----
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyProc->xid = InvalidTransactionId;
MyProc->xmin = InvalidTransactionId;
+ MyProc->inVacuum = false; /* must be cleared with xid/xmin */
+ MyProc->nonInVacuumXmin = InvalidTransactionId; /* this too */
/* Clear the subtransaction-XID cache too while holding the lock */
MyProc->subxids.nxids = 0;
***************
*** 1740,1745 ****
--- 1742,1749 ----
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyProc->xid = InvalidTransactionId;
MyProc->xmin = InvalidTransactionId;
+ MyProc->inVacuum = false; /* must be cleared with xid/xmin */
+ MyProc->nonInVacuumXmin = InvalidTransactionId; /* this too */
/* Clear the subtransaction-XID cache too while holding the lock */
MyProc->subxids.nxids = 0;
***************
*** 1902,1907 ****
--- 1906,1913 ----
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyProc->xid = InvalidTransactionId;
MyProc->xmin = InvalidTransactionId;
+ MyProc->inVacuum = false; /* must be cleared with xid/xmin */
+ MyProc->nonInVacuumXmin = InvalidTransactionId; /* this too */
/* Clear the subtransaction-XID cache too while holding the lock */
MyProc->subxids.nxids = 0;
Index: src/backend/access/transam/xlog.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/xlog.c,v
retrieving revision 1.222
diff -c -r1.222 xlog.c
*** src/backend/access/transam/xlog.c 29 Oct 2005 00:31:50 -0000 1.222
--- src/backend/access/transam/xlog.c 21 Dec 2005 23:09:34 -0000
***************
*** 5294,5300 ****
* StartupSUBTRANS hasn't been called yet.
*/
if (!InRecovery)
! TruncateSUBTRANS(GetOldestXmin(true));
if (!shutdown)
ereport(DEBUG2,
--- 5294,5300 ----
* StartupSUBTRANS hasn't been called yet.
*/
if (!InRecovery)
! TruncateSUBTRANS(GetOldestXmin(true, false));
if (!shutdown)
ereport(DEBUG2,
Index: src/backend/catalog/index.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/index.c,v
retrieving revision 1.261
diff -c -r1.261 index.c
*** src/backend/catalog/index.c 15 Oct 2005 02:49:12 -0000 1.261
--- src/backend/catalog/index.c 21 Dec 2005 23:09:34 -0000
***************
*** 1427,1433 ****
else
{
snapshot = SnapshotAny;
! OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared);
}
scan = heap_beginscan(heapRelation, /* relation */
--- 1427,1434 ----
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: /projects/cvsroot/pgsql/src/backend/commands/vacuum.c,v
retrieving revision 1.317
diff -c -r1.317 vacuum.c
*** src/backend/commands/vacuum.c 15 Oct 2005 02:49:16 -0000 1.317
--- src/backend/commands/vacuum.c 21 Dec 2005 23:09:35 -0000
***************
*** 36,41 ****
--- 36,42 ----
#include "executor/executor.h"
#include "miscadmin.h"
#include "storage/freespace.h"
+ #include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "tcop/pquery.h"
***************
*** 370,377 ****
* cutoff with which we vacuum shared relations, it is not possible
* for that database to have a cutoff newer than OLDXMIN recorded in
* pg_database.
*/
! vacuum_set_xid_limits(vacstmt, false,
&initialOldestXmin,
&initialFreezeLimit);
}
--- 371,381 ----
* cutoff with which we vacuum shared relations, it is not possible
* for that database to have a cutoff newer than OLDXMIN recorded in
* pg_database.
+ *
+ * We can't ignore concurrent lazy VACUUMs, because these values will
+ * be used to truncate clog below.
*/
! vacuum_set_xid_limits(vacstmt, false,false,
&initialOldestXmin,
&initialFreezeLimit);
}
***************
*** 610,622 ****
* vacuum_set_xid_limits() -- compute oldest-Xmin and freeze cutoff points
*/
void
! vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel,
TransactionId *oldestXmin,
TransactionId *freezeLimit)
{
TransactionId limit;
! *oldestXmin = GetOldestXmin(sharedRel);
Assert(TransactionIdIsNormal(*oldestXmin));
--- 614,627 ----
* vacuum_set_xid_limits() -- compute oldest-Xmin and freeze cutoff points
*/
void
! vacuum_set_xid_limits(VacuumStmt *vacstmt,
! bool sharedRel, bool ignoreVacuum,
TransactionId *oldestXmin,
TransactionId *freezeLimit)
{
TransactionId limit;
! *oldestXmin = GetOldestXmin(sharedRel, ignoreVacuum);
Assert(TransactionIdIsNormal(*oldestXmin));
***************
*** 671,676 ****
--- 676,686 ----
* 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.
*/
***************
*** 951,958 ****
/* 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
--- 961,995 ----
/* 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
***************
*** 1129,1135 ****
i;
VRelStats *vacrelstats;
! vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared,
&OldestXmin, &FreezeLimit);
/*
--- 1166,1172 ----
i;
VRelStats *vacrelstats;
! vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared, true,
&OldestXmin, &FreezeLimit);
/*
Index: src/backend/commands/vacuumlazy.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v
retrieving revision 1.61
diff -c -r1.61 vacuumlazy.c
*** src/backend/commands/vacuumlazy.c 15 Oct 2005 02:49:16 -0000 1.61
--- src/backend/commands/vacuumlazy.c 21 Dec 2005 23:09:36 -0000
***************
*** 140,146 ****
else
elevel = DEBUG2;
! vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared,
&OldestXmin, &FreezeLimit);
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
--- 140,146 ----
else
elevel = DEBUG2;
! vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared, true,
&OldestXmin, &FreezeLimit);
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
Index: src/backend/storage/ipc/procarray.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/ipc/procarray.c,v
retrieving revision 1.7
diff -c -r1.7 procarray.c
*** src/backend/storage/ipc/procarray.c 15 Oct 2005 02:49:25 -0000 1.7
--- src/backend/storage/ipc/procarray.c 21 Dec 2005 23:09:36 -0000
***************
*** 387,406 ****
* 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;
--- 387,410 ----
* 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;
***************
*** 424,429 ****
--- 428,436 ----
{
PGPROC *proc = arrayP->procs[index];
+ if (ignoreVacuum && proc->inVacuum)
+ continue;
+
if (allDbs || proc->databaseId == MyDatabaseId)
{
/* Fetch xid just once - see GetNewTransactionId */
***************
*** 433,439 ****
{
if (TransactionIdPrecedes(xid, result))
result = xid;
! xid = proc->xmin;
if (TransactionIdIsNormal(xid))
if (TransactionIdPrecedes(xid, result))
result = xid;
--- 440,449 ----
{
if (TransactionIdPrecedes(xid, result))
result = xid;
! if (ignoreVacuum)
! xid = proc->nonInVacuumXmin;
! else
! xid = proc->xmin;
if (TransactionIdIsNormal(xid))
if (TransactionIdPrecedes(xid, result))
result = xid;
***************
*** 471,477 ****
* older than this are known not running any more.
* RecentGlobalXmin: the global xmin (oldest TransactionXmin across all
* running transactions). This is the same computation done by
! * GetOldestXmin(TRUE).
*----------
*/
Snapshot
--- 481,487 ----
* older than this are known not running any more.
* RecentGlobalXmin: the global xmin (oldest TransactionXmin across all
* running transactions). This is the same computation done by
! * GetOldestXmin(TRUE,FALSE).
*----------
*/
Snapshot
***************
*** 481,486 ****
--- 491,497 ----
TransactionId xmin;
TransactionId xmax;
TransactionId globalxmin;
+ TransactionId noninvacuumxmin;
int index;
int count = 0;
***************
*** 514,520 ****
errmsg("out of memory")));
}
! globalxmin = xmin = GetTopTransactionId();
/*
* If we are going to set MyProc->xmin then we'd better get exclusive
--- 525,531 ----
errmsg("out of memory")));
}
! globalxmin = xmin = noninvacuumxmin = GetTopTransactionId();
/*
* If we are going to set MyProc->xmin then we'd better get exclusive
***************
*** 571,578 ****
TransactionIdFollowsOrEquals(xid, xmax))
continue;
! if (TransactionIdPrecedes(xid, xmin))
xmin = xid;
snapshot->xip[count] = xid;
count++;
--- 582,592 ----
TransactionIdFollowsOrEquals(xid, xmax))
continue;
! if (TransactionIdPrecedes(xid, xmin)) {
xmin = xid;
+ if (proc->inVacuum==false)
+ noninvacuumxmin = xid;
+ }
snapshot->xip[count] = xid;
count++;
***************
*** 583,590 ****
globalxmin = xid;
}
! if (serializable)
MyProc->xmin = TransactionXmin = xmin;
LWLockRelease(ProcArrayLock);
--- 597,606 ----
globalxmin = xid;
}
! if (serializable) {
MyProc->xmin = TransactionXmin = xmin;
+ MyProc->nonInVacuumXmin = noninvacuumxmin;
+ }
LWLockRelease(ProcArrayLock);
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.167
diff -c -r1.167 proc.c
*** src/backend/storage/lmgr/proc.c 15 Oct 2005 02:49:26 -0000 1.167
--- src/backend/storage/lmgr/proc.c 21 Dec 2005 23:09:37 -0000
***************
*** 259,264 ****
--- 259,266 ----
MyProc->databaseId = MyDatabaseId;
/* Will be set properly after the session role id is determined */
MyProc->roleId = InvalidOid;
+ MyProc->inVacuum = false;
+ MyProc->nonInVacuumXmin = InvalidTransactionId;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
***************
*** 355,360 ****
--- 357,364 ----
MyProc->xmin = InvalidTransactionId;
MyProc->databaseId = MyDatabaseId;
MyProc->roleId = InvalidOid;
+ MyProc->inVacuum = false;
+ MyProc->nonInVacuumXmin = InvalidTransactionId;
MyProc->lwWaiting = false;
MyProc->lwExclusive = false;
MyProc->lwWaitLink = NULL;
Index: src/include/commands/vacuum.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/commands/vacuum.h,v
retrieving revision 1.62
diff -c -r1.62 vacuum.h
*** src/include/commands/vacuum.h 15 Oct 2005 02:49:44 -0000 1.62
--- src/include/commands/vacuum.h 21 Dec 2005 23:09:37 -0000
***************
*** 118,124 ****
BlockNumber num_pages,
double num_tuples,
bool hasindex);
! extern void vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel,
TransactionId *oldestXmin,
TransactionId *freezeLimit);
extern bool vac_is_partial_index(Relation indrel);
--- 118,125 ----
BlockNumber num_pages,
double num_tuples,
bool hasindex);
! extern void vacuum_set_xid_limits(VacuumStmt *vacstmt,
! bool sharedRel, bool ignoreVacuum,
TransactionId *oldestXmin,
TransactionId *freezeLimit);
extern bool vac_is_partial_index(Relation indrel);
Index: src/include/storage/proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/proc.h,v
retrieving revision 1.84
diff -c -r1.84 proc.h
*** src/include/storage/proc.h 15 Oct 2005 02:49:46 -0000 1.84
--- src/include/storage/proc.h 21 Dec 2005 23:09:37 -0000
***************
*** 73,78 ****
--- 73,83 ----
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 VACUUM */
+
+ TransactionId nonInVacuumXmin; /* same as xmin with transactions where
+ * (proc->inVacuum == true) excluded */
+
/* 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: /projects/cvsroot/pgsql/src/include/storage/procarray.h,v
retrieving revision 1.6
diff -c -r1.6 procarray.h
*** src/include/storage/procarray.h 15 Oct 2005 02:49:46 -0000 1.6
--- src/include/storage/procarray.h 21 Dec 2005 23:09:37 -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 4: Have you searched our list archives?
http://archives.postgresql.org