Allow ANALYZE to run in a transaction.
This commit is contained in:
parent
deec3cb91c
commit
c66eb00adc
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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;
|
|||||||
|
|
||||||
|
|
||||||
/* 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);
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
MemoryContextDelete(vac_context);
|
MemoryContextDelete(vac_context);
|
||||||
vac_context = NULL;
|
vac_context = NULL;
|
||||||
|
|
||||||
|
if (vacstmt->analyze && !vacstmt->vacuum)
|
||||||
|
MemoryContextDelete(anl_context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user