Commit c66eb00a authored by Bruce Momjian's avatar Bruce Momjian

Allow ANALYZE to run in a transaction.

parent deec3cb9
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.35 2002/05/24 18:57:55 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.36 2002/06/13 19:52:02 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -155,15 +155,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -155,15 +155,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
else else
elevel = DEBUG1; elevel = DEBUG1;
/*
* Begin a transaction for analyzing this relation.
*
* Note: All memory allocated during ANALYZE will live in
* TransactionCommandContext or a subcontext thereof, so it will all
* be released by transaction commit at the end of this routine.
*/
StartTransactionCommand();
/* /*
* Check for user-requested abort. Note we want this to be inside a * Check for user-requested abort. Note we want this to be inside a
* transaction, so xact.c doesn't issue useless WARNING. * transaction, so xact.c doesn't issue useless WARNING.
...@@ -177,10 +168,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -177,10 +168,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
if (!SearchSysCacheExists(RELOID, if (!SearchSysCacheExists(RELOID,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
0, 0, 0)) 0, 0, 0))
{
CommitTransactionCommand();
return; return;
}
/* /*
* Open the class, getting only a read lock on it, and check * Open the class, getting only a read lock on it, and check
...@@ -196,7 +184,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -196,7 +184,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
elog(WARNING, "Skipping \"%s\" --- only table or database owner can ANALYZE it", elog(WARNING, "Skipping \"%s\" --- only table or database owner can ANALYZE it",
RelationGetRelationName(onerel)); RelationGetRelationName(onerel));
relation_close(onerel, AccessShareLock); relation_close(onerel, AccessShareLock);
CommitTransactionCommand();
return; return;
} }
...@@ -211,7 +198,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -211,7 +198,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
elog(WARNING, "Skipping \"%s\" --- can not process indexes, views or special system tables", elog(WARNING, "Skipping \"%s\" --- can not process indexes, views or special system tables",
RelationGetRelationName(onerel)); RelationGetRelationName(onerel));
relation_close(onerel, AccessShareLock); relation_close(onerel, AccessShareLock);
CommitTransactionCommand();
return; return;
} }
...@@ -222,7 +208,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -222,7 +208,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
strcmp(RelationGetRelationName(onerel), StatisticRelationName) == 0) strcmp(RelationGetRelationName(onerel), StatisticRelationName) == 0)
{ {
relation_close(onerel, AccessShareLock); relation_close(onerel, AccessShareLock);
CommitTransactionCommand();
return; return;
} }
...@@ -283,7 +268,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -283,7 +268,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
if (attr_cnt <= 0) if (attr_cnt <= 0)
{ {
relation_close(onerel, NoLock); relation_close(onerel, NoLock);
CommitTransactionCommand();
return; return;
} }
...@@ -370,9 +354,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -370,9 +354,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
* entries we made in pg_statistic.) * entries we made in pg_statistic.)
*/ */
relation_close(onerel, NoLock); relation_close(onerel, NoLock);
/* Commit and release working memory */
CommitTransactionCommand();
} }
/* /*
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.226 2002/05/24 18:57:56 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.227 2002/06/13 19:52:02 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -110,8 +110,6 @@ static TransactionId initialFreezeLimit; ...@@ -110,8 +110,6 @@ static TransactionId initialFreezeLimit;
/* non-export function prototypes */ /* non-export function prototypes */
static void vacuum_init(VacuumStmt *vacstmt);
static void vacuum_shutdown(VacuumStmt *vacstmt);
static List *getrels(const RangeVar *vacrel, const char *stmttype); static List *getrels(const RangeVar *vacrel, const char *stmttype);
static void vac_update_dbstats(Oid dbid, static void vac_update_dbstats(Oid dbid,
TransactionId vacuumXID, TransactionId vacuumXID,
...@@ -160,6 +158,8 @@ static bool enough_space(VacPage vacpage, Size len); ...@@ -160,6 +158,8 @@ static bool enough_space(VacPage vacpage, Size len);
void void
vacuum(VacuumStmt *vacstmt) vacuum(VacuumStmt *vacstmt)
{ {
MemoryContext anl_context,
old_context;
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE"; const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
List *vrl, List *vrl,
*cur; *cur;
...@@ -178,11 +178,11 @@ vacuum(VacuumStmt *vacstmt) ...@@ -178,11 +178,11 @@ vacuum(VacuumStmt *vacstmt)
* user's transaction too, which would certainly not be the desired * user's transaction too, which would certainly not be the desired
* behavior. * behavior.
*/ */
if (IsTransactionBlock()) if (vacstmt->vacuum && IsTransactionBlock())
elog(ERROR, "%s cannot run inside a BEGIN/END block", stmttype); elog(ERROR, "%s cannot run inside a BEGIN/END block", stmttype);
/* Running VACUUM from a function would free the function context */ /* Running VACUUM from a function would free the function context */
if (!MemoryContextContains(QueryContext, vacstmt)) if (vacstmt->vacuum && !MemoryContextContains(QueryContext, vacstmt))
elog(ERROR, "%s cannot be executed from a function", stmttype); elog(ERROR, "%s cannot be executed from a function", stmttype);
/* /*
...@@ -203,38 +203,17 @@ vacuum(VacuumStmt *vacstmt) ...@@ -203,38 +203,17 @@ vacuum(VacuumStmt *vacstmt)
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
if (vacstmt->analyze && !vacstmt->vacuum)
anl_context = AllocSetContextCreate(QueryContext,
"Analyze",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/* Build list of relations to process (note this lives in vac_context) */ /* Build list of relations to process (note this lives in vac_context) */
vrl = getrels(vacstmt->relation, stmttype); vrl = getrels(vacstmt->relation, stmttype);
/* /*
* Start up the vacuum cleaner.
*/
vacuum_init(vacstmt);
/*
* Process each selected relation. We are careful to process each
* relation in a separate transaction in order to avoid holding too
* many locks at one time. Also, if we are doing VACUUM ANALYZE, the
* ANALYZE part runs as a separate transaction from the VACUUM to
* further reduce locking.
*/
foreach(cur, vrl)
{
Oid relid = (Oid) lfirsti(cur);
if (vacstmt->vacuum)
vacuum_rel(relid, vacstmt, RELKIND_RELATION);
if (vacstmt->analyze)
analyze_rel(relid, vacstmt);
}
/* clean up */
vacuum_shutdown(vacstmt);
}
/*
* vacuum_init(), vacuum_shutdown() -- start up and shut down the vacuum cleaner.
*
* Formerly, there was code here to prevent more than one VACUUM from * Formerly, there was code here to prevent more than one VACUUM from
* executing concurrently in the same database. However, there's no * executing concurrently in the same database. However, there's no
* good reason to prevent that, and manually removing lockfiles after * good reason to prevent that, and manually removing lockfiles after
...@@ -252,10 +231,9 @@ vacuum(VacuumStmt *vacstmt) ...@@ -252,10 +231,9 @@ vacuum(VacuumStmt *vacstmt)
* vacuum_shutdown() to match the commit waiting for us back in * vacuum_shutdown() to match the commit waiting for us back in
* PostgresMain(). * PostgresMain().
*/ */
static void if (vacstmt->vacuum)
vacuum_init(VacuumStmt *vacstmt) {
{ if (vacstmt->relation == NULL)
if (vacstmt->vacuum && vacstmt->relation == NULL)
{ {
/* /*
* Compute the initially applicable OldestXmin and FreezeLimit * Compute the initially applicable OldestXmin and FreezeLimit
...@@ -280,11 +258,44 @@ vacuum_init(VacuumStmt *vacstmt) ...@@ -280,11 +258,44 @@ vacuum_init(VacuumStmt *vacstmt)
/* matches the StartTransaction in PostgresMain() */ /* matches the StartTransaction in PostgresMain() */
CommitTransactionCommand(); CommitTransactionCommand();
} }
static void /*
vacuum_shutdown(VacuumStmt *vacstmt) * Process each selected relation. We are careful to process each
{ * relation in a separate transaction in order to avoid holding too
* many locks at one time. Also, if we are doing VACUUM ANALYZE, the
* ANALYZE part runs as a separate transaction from the VACUUM to
* further reduce locking.
*/
foreach(cur, vrl)
{
Oid relid = (Oid) lfirsti(cur);
if (vacstmt->vacuum)
vacuum_rel(relid, vacstmt, RELKIND_RELATION);
if (vacstmt->analyze)
{
/* If we vacuumed, use new transaction for analyze. */
if (vacstmt->vacuum)
StartTransactionCommand();
else
old_context = MemoryContextSwitchTo(anl_context);
analyze_rel(relid, vacstmt);
if (vacstmt->vacuum)
CommitTransactionCommand();
else
{
MemoryContextResetAndDeleteChildren(anl_context);
MemoryContextSwitchTo(old_context);
}
}
}
/* clean up */
if (vacstmt->vacuum)
{
/* on entry, we are not in a transaction */ /* on entry, we are not in a transaction */
/* matches the CommitTransaction in PostgresMain() */ /* matches the CommitTransaction in PostgresMain() */
...@@ -295,12 +306,13 @@ vacuum_shutdown(VacuumStmt *vacstmt) ...@@ -295,12 +306,13 @@ vacuum_shutdown(VacuumStmt *vacstmt)
* row with info about the transaction IDs used, and try to truncate * row with info about the transaction IDs used, and try to truncate
* pg_clog. * pg_clog.
*/ */
if (vacstmt->vacuum && vacstmt->relation == NULL) if (vacstmt->relation == NULL)
{ {
vac_update_dbstats(MyDatabaseId, vac_update_dbstats(MyDatabaseId,
initialOldestXmin, initialFreezeLimit); initialOldestXmin, initialFreezeLimit);
vac_truncate_clog(initialOldestXmin, initialFreezeLimit); vac_truncate_clog(initialOldestXmin, initialFreezeLimit);
} }
}
/* /*
* Clean up working storage --- note we must do this after * Clean up working storage --- note we must do this after
...@@ -309,6 +321,10 @@ vacuum_shutdown(VacuumStmt *vacstmt) ...@@ -309,6 +321,10 @@ vacuum_shutdown(VacuumStmt *vacstmt)
*/ */
MemoryContextDelete(vac_context); MemoryContextDelete(vac_context);
vac_context = NULL; vac_context = NULL;
if (vacstmt->analyze && !vacstmt->vacuum)
MemoryContextDelete(anl_context);
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment