On E, 2005-05-23 at 11:42 -0400, Tom Lane wrote:
> Hannu Krosing <[EMAIL PROTECTED]> writes:
> > I can't think of any other cases where it could matter, as at least the
> > work done inside vacuum_rel() itself seema non-rollbackable.
>
> VACUUM FULL's tuple-moving is definitely roll-back-able, so it might be
> prudent to only do this for lazy VACUUM. But on the other hand, VACUUM
> FULL holds an exclusive lock on the table so no one else is going to see
> its effects concurrently anyway.
Ok, this is a new version of the vacuum patch with the following changes
following some suggestions in this thread.
* changed the patch to affect only lazy vacuum
* moved inVacuum handling to use PG_TRY
* moved vac_update_relstats() out of lazy_vacuum_rel into a separate
transaction. The code to do this may not be the prettiest, maybe it
should use a separate struct.
--
Hannu Krosing <[EMAIL PROTECTED]>
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.209
diff -c -r1.209 xact.c
*** src/backend/access/transam/xact.c 29 Jun 2005 22:51:53 -0000 1.209
--- src/backend/access/transam/xact.c 3 Jul 2005 15:59:09 -0000
***************
*** 1402,1407 ****
--- 1402,1416 ----
AfterTriggerBeginXact();
/*
+ * mark the transaction as not VACUUM (vacuum_rel will set isVacuum
+ * to true directly after calling BeginTransactionCommand() )
+ *
+ * this can probably be moved to be done only once when establishing
+ * connection as this is now quaranteedto be reset to false in vacuum.c
+ */
+ MyProc->inVacuum = false;
+
+ /*
* done with start processing, set current transaction state to "in
* progress"
*/
Index: src/backend/commands/vacuum.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/vacuum.c,v
retrieving revision 1.310
diff -c -r1.310 vacuum.c
*** src/backend/commands/vacuum.c 14 Jun 2005 22:15:32 -0000 1.310
--- src/backend/commands/vacuum.c 3 Jul 2005 15:59:15 -0000
***************
*** 37,42 ****
--- 37,43 ----
#include "miscadmin.h"
#include "storage/freespace.h"
#include "storage/procarray.h"
+ #include "storage/proc.h"
#include "storage/smgr.h"
#include "tcop/pquery.h"
#include "utils/acl.h"
***************
*** 903,908 ****
--- 904,913 ----
Oid toast_relid;
bool result;
+ BlockNumber stats_rel_pages=0;
+ double stats_rel_tuples=0;
+ bool stats_hasindex=false;
+
/* Begin a transaction for vacuuming this relation */
StartTransactionCommand();
/* functions in indexes may want a snapshot set */
***************
*** 1016,1039 ****
*/
toast_relid = onerel->rd_rel->reltoastrelid;
! /*
! * Do the actual work --- either FULL or "lazy" vacuum
! */
! if (vacstmt->full)
! full_vacuum_rel(onerel, vacstmt);
! else
! lazy_vacuum_rel(onerel, vacstmt);
! result = true; /* did the vacuum */
! /* all done with this class, but hold lock until commit */
! relation_close(onerel, NoLock);
! /*
! * Complete the transaction and free all temporary memory used.
! */
! StrategyHintVacuum(false);
! CommitTransactionCommand();
/*
* If the relation has a secondary toast rel, vacuum that too while we
--- 1021,1071 ----
*/
toast_relid = onerel->rd_rel->reltoastrelid;
! PG_TRY();
! {
! /*
! * Do the actual work --- either FULL or "lazy" vacuum
! */
! if (vacstmt->full)
! full_vacuum_rel(onerel, vacstmt);
! else
! /* mark this transaction as being a lazy vacuum */
! MyProc->inVacuum = true;
! lazy_vacuum_rel(onerel, vacstmt, &stats_rel_pages, &stats_rel_tuples, &stats_hasindex);
! result = true; /* did the vacuum */
! /* all done with this class, but hold lock until commit */
! relation_close(onerel, NoLock);
!
! /*
! * Complete the transaction and free all temporary memory used.
! */
! StrategyHintVacuum(false);
! CommitTransactionCommand();
! }
! PG_CATCH();
! {
! /* make sure in-vacuum flag is cleared is cleared */
! MyProc->inVacuum = false;
! PG_RE_THROW();
! }
! PG_END_TRY();
! MyProc->inVacuum = false;
!
!
! /* use yet another transaction for saving stats from lazy_vacuum_rel into pg_class */
! if (stats_rel_pages > 0) {
! StartTransactionCommand();
! ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); /* is this needed ? */
! /* Update statistics in pg_class */
! vac_update_relstats(RelationGetRelid(onerel),
! stats_rel_pages,
! stats_rel_tuples,
! stats_hasindex);
! CommitTransactionCommand();
! }
/*
* If the relation has a secondary toast rel, vacuum that too while we
Index: src/backend/commands/vacuumlazy.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v
retrieving revision 1.54
diff -c -r1.54 vacuumlazy.c
*** src/backend/commands/vacuumlazy.c 19 May 2005 21:35:46 -0000 1.54
--- src/backend/commands/vacuumlazy.c 3 Jul 2005 15:59:17 -0000
***************
*** 128,134 ****
* and locked the relation.
*/
void
! lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
{
LVRelStats *vacrelstats;
Relation *Irel;
--- 128,134 ----
* and locked the relation.
*/
void
! lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, BlockNumber *stats_rel_pages, double *stats_rel_tuples, bool *stats_hasindex)
{
LVRelStats *vacrelstats;
Relation *Irel;
***************
*** 175,184 ****
--- 175,190 ----
lazy_update_fsm(onerel, vacrelstats);
/* Update statistics in pg_class */
+ /*
vac_update_relstats(RelationGetRelid(onerel),
vacrelstats->rel_pages,
vacrelstats->rel_tuples,
hasindex);
+ */
+ /* return values for setting relstats in another transaction */
+ *stats_rel_pages = vacrelstats->rel_pages;
+ *stats_rel_tuples = vacrelstats->rel_tuples;
+ *stats_hasindex = hasindex;
}
Index: src/backend/storage/ipc/procarray.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/ipc/procarray.c,v
retrieving revision 1.3
diff -c -r1.3 procarray.c
*** src/backend/storage/ipc/procarray.c 17 Jun 2005 22:32:45 -0000 1.3
--- src/backend/storage/ipc/procarray.c 3 Jul 2005 15:59:17 -0000
***************
*** 423,429 ****
{
PGPROC *proc = arrayP->procs[index];
! if (allDbs || proc->databaseId == MyDatabaseId)
{
/* Fetch xid just once - see GetNewTransactionId */
TransactionId xid = proc->xid;
--- 423,431 ----
{
PGPROC *proc = arrayP->procs[index];
! /* don't use xid of transactions running lazy vacuum */
! if ( (proc->inVacuum == false)
! && (allDbs || proc->databaseId == MyDatabaseId))
{
/* Fetch xid just once - see GetNewTransactionId */
TransactionId xid = proc->xid;
Index: src/include/commands/vacuum.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/commands/vacuum.h,v
retrieving revision 1.59
diff -c -r1.59 vacuum.h
*** src/include/commands/vacuum.h 31 Dec 2004 22:03:28 -0000 1.59
--- src/include/commands/vacuum.h 3 Jul 2005 15:59:17 -0000
***************
*** 142,148 ****
extern void vacuum_delay_point(void);
/* in commands/vacuumlazy.c */
! extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
/* in commands/analyze.c */
extern void analyze_rel(Oid relid, VacuumStmt *vacstmt);
--- 142,151 ----
extern void vacuum_delay_point(void);
/* in commands/vacuumlazy.c */
! extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
! BlockNumber *stats_rel_pages,
! double *stats_rel_tuples,
! bool *stats_hasindex);
/* in commands/analyze.c */
extern void analyze_rel(Oid relid, VacuumStmt *vacstmt);
Index: src/include/storage/proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/proc.h,v
retrieving revision 1.79
diff -c -r1.79 proc.h
*** src/include/storage/proc.h 17 Jun 2005 22:32:50 -0000 1.79
--- src/include/storage/proc.h 3 Jul 2005 15:59:18 -0000
***************
*** 69,74 ****
--- 69,80 ----
* were starting our xact: vacuum must not
* remove tuples deleted by xid >= xmin ! */
+ bool inVacuum; /* true if current command is vacuum.
+ * used by other vacuum commands
+ * as xid or xmin of this cmd need not be used
+ * when finding global xmin for removing
+ * tuples */
+
int pid; /* This backend's process id, or 0 */
Oid databaseId; /* OID of database this backend is using */
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match