1313 *
1414 *
1515 * IDENTIFICATION
16- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.228 2002/06/1519:54:23 momjian Exp $
16+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.229 2002/06/1521:52:31 tgl Exp $
1717 *
1818 *-------------------------------------------------------------------------
1919 */
@@ -158,9 +158,8 @@ static bool enough_space(VacPage vacpage, Size len);
158158void
159159vacuum (VacuumStmt * vacstmt )
160160{
161- MemoryContext anl_context ,
162- old_context ;
163161const char * stmttype = vacstmt -> vacuum ?"VACUUM" :"ANALYZE" ;
162+ MemoryContext anl_context = NULL ;
164163List * vrl ,
165164* cur ;
166165
@@ -188,7 +187,8 @@ vacuum(VacuumStmt *vacstmt)
188187/*
189188 * Send info about dead objects to the statistics collector
190189 */
191- pgstat_vacuum_tabstat ();
190+ if (vacstmt -> vacuum )
191+ pgstat_vacuum_tabstat ();
192192
193193/*
194194 * Create special memory context for cross-transaction storage.
@@ -203,6 +203,10 @@ vacuum(VacuumStmt *vacstmt)
203203ALLOCSET_DEFAULT_INITSIZE ,
204204ALLOCSET_DEFAULT_MAXSIZE );
205205
206+ /*
207+ * If we are running only ANALYZE, we don't need per-table transactions,
208+ * but we still need a memory context with table lifetime.
209+ */
206210if (vacstmt -> analyze && !vacstmt -> vacuum )
207211anl_context = AllocSetContextCreate (QueryContext ,
208212"Analyze" ,
@@ -214,28 +218,40 @@ vacuum(VacuumStmt *vacstmt)
214218vrl = getrels (vacstmt -> relation ,stmttype );
215219
216220/*
217- *Formerly, there was code here to prevent more than one VACUUM from
218- *executing concurrently in the same database. However, there's no
219- *good reason to prevent that, and manually removing lockfiles after
220- *a vacuum crash was a pain for dbadmins. So, forget about lockfiles,
221- *and just rely on the locks we grab on each target table
222- *to ensure that there aren't two VACUUMs running on the same table
223- *at the same time.
221+ * Formerly, there was code here to prevent more than one VACUUM from
222+ * executing concurrently in the same database. However, there's no
223+ * good reason to prevent that, and manually removing lockfiles after
224+ * a vacuum crash was a pain for dbadmins. So, forget about lockfiles,
225+ * and just rely on the locks we grab on each target table
226+ * to ensure that there aren't two VACUUMs running on the same table
227+ * at the same time.
228+ */
229+
230+ /*
231+ * The strangeness with committing and starting transactions here is due
232+ * to wanting to run each table's VACUUM as a separate transaction, so
233+ * that we don't hold locks unnecessarily long. Also, if we are doing
234+ * VACUUM ANALYZE, the ANALYZE part runs as a separate transaction from
235+ * the VACUUM to further reduce locking.
236+ *
237+ * vacuum_rel expects to be entered with no transaction active; it will
238+ * start and commit its own transaction. But we are called by an SQL
239+ * command, and so we are executing inside a transaction already. We
240+ * commit the transaction started in PostgresMain() here, and start
241+ * another one before exiting to match the commit waiting for us back in
242+ * PostgresMain().
224243 *
225- *The strangeness with committing and starting transactions in the
226- *init and shutdown routines is due to the fact that the vacuum cleaner
227- *is invoked via an SQL command, and so is already executing inside
228- *a transaction.We need to leave ourselves in a predictable state
229- *on entry and exit to the vacuum cleaner. We commit the transaction
230- *started in PostgresMain() inside vacuum_init(), and start one in
231- *vacuum_shutdown() to match the commit waiting for us back in
232- *PostgresMain().
244+ * In the case of an ANALYZE statement (no vacuum, just analyze) it's
245+ * okay to run the whole thing in the outer transaction, and so we skip
246+ * transaction start/stop operations.
233247 */
234248if (vacstmt -> vacuum )
235249{
236250if (vacstmt -> relation == NULL )
237251{
238252/*
253+ * It's a database-wide VACUUM.
254+ *
239255 * Compute the initially applicable OldestXmin and FreezeLimit
240256 * XIDs, so that we can record these values at the end of the
241257 * VACUUM. Note that individual tables may well be processed with
@@ -261,11 +277,7 @@ vacuum(VacuumStmt *vacstmt)
261277}
262278
263279/*
264- * Process each selected relation.We are careful to process each
265- * relation in a separate transaction in order to avoid holding too
266- * many locks at one time.Also, if we are doing VACUUM ANALYZE, the
267- * ANALYZE part runs as a separate transaction from the VACUUM to
268- * further reduce locking.
280+ * Loop to process each selected relation.
269281 */
270282foreach (cur ,vrl )
271283{
@@ -275,7 +287,14 @@ vacuum(VacuumStmt *vacstmt)
275287vacuum_rel (relid ,vacstmt ,RELKIND_RELATION );
276288if (vacstmt -> analyze )
277289{
278- /* If we vacuumed, use new transaction for analyze. */
290+ MemoryContext old_context = NULL ;
291+
292+ /*
293+ * If we vacuumed, use new transaction for analyze. Otherwise,
294+ * we can use the outer transaction, but we still need to call
295+ * analyze_rel in a memory context that will be cleaned up on
296+ * return (else we leak memory while processing multiple tables).
297+ */
279298if (vacstmt -> vacuum )
280299StartTransactionCommand ();
281300else
@@ -287,16 +306,18 @@ vacuum(VacuumStmt *vacstmt)
287306CommitTransactionCommand ();
288307else
289308{
290- MemoryContextResetAndDeleteChildren (anl_context );
291309MemoryContextSwitchTo (old_context );
310+ MemoryContextResetAndDeleteChildren (anl_context );
292311}
293312}
294313}
295314
296- /* clean up */
315+ /*
316+ * Finish up processing.
317+ */
297318if (vacstmt -> vacuum )
298319{
299- /*on entry , we are not in a transaction */
320+ /*here , we are not in a transaction */
300321
301322/* matches the CommitTransaction in PostgresMain() */
302323StartTransactionCommand ();
@@ -322,9 +343,8 @@ vacuum(VacuumStmt *vacstmt)
322343MemoryContextDelete (vac_context );
323344vac_context = NULL ;
324345
325- if (vacstmt -> analyze && ! vacstmt -> vacuum )
346+ if (anl_context )
326347MemoryContextDelete (anl_context );
327-
328348}
329349
330350/*