1010 *
1111 *
1212 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.36 2007/03/23 21:23:13 alvherre Exp $
13+ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.37 2007/03/23 21:45:17 alvherre Exp $
1414 *
1515 *-------------------------------------------------------------------------
1616 */
@@ -118,6 +118,7 @@ static pid_t avworker_forkexec(void);
118118NON_EXEC_STATIC void AutoVacWorkerMain (int argc , char * argv []);
119119NON_EXEC_STATIC void AutoVacLauncherMain (int argc , char * argv []);
120120
121+ static void do_start_worker (void );
121122static void do_autovacuum (PgStat_StatDBEntry * dbentry );
122123static List * autovac_get_database_list (void );
123124static void test_rel_for_autovac (Oid relid , PgStat_StatTabEntry * tabentry ,
@@ -218,9 +219,6 @@ NON_EXEC_STATIC void
218219AutoVacLauncherMain (int argc , char * argv [])
219220{
220221 sigjmp_buf local_sigjmp_buf ;
221- List * dblist ;
222- bool for_xid_wrap ;
223- autovac_dbase * db ;
224222 MemoryContext avlauncher_cxt ;
225223
226224 /* we are a postmaster subprocess now */
@@ -358,8 +356,6 @@ AutoVacLauncherMain(int argc, char *argv[])
358356
359357 for (;;)
360358 {
361- TransactionId xidForceLimit ;
362- ListCell * cell ;
363359 int worker_pid ;
364360
365361 /*
@@ -407,86 +403,8 @@ AutoVacLauncherMain(int argc, char *argv[])
407403 }
408404 }
409405
410- /* Get a list of databases */
411- dblist = autovac_get_database_list ();
406+ do_start_worker ();
412407
413- /*
414- * Determine the oldest datfrozenxid/relfrozenxid that we will allow
415- * to pass without forcing a vacuum. (This limit can be tightened for
416- * particular tables, but not loosened.)
417- */
418- recentXid = ReadNewTransactionId ();
419- xidForceLimit = recentXid - autovacuum_freeze_max_age ;
420- /* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
421- if (xidForceLimit < FirstNormalTransactionId )
422- xidForceLimit -= FirstNormalTransactionId ;
423-
424- /*
425- * Choose a database to connect to. We pick the database that was least
426- * recently auto-vacuumed, or one that needs vacuuming to prevent Xid
427- * wraparound-related data loss. If any db at risk of wraparound is
428- * found, we pick the one with oldest datfrozenxid, independently of
429- * autovacuum times.
430- *
431- * Note that a database with no stats entry is not considered, except for
432- * Xid wraparound purposes. The theory is that if no one has ever
433- * connected to it since the stats were last initialized, it doesn't need
434- * vacuuming.
435- *
436- * XXX This could be improved if we had more info about whether it needs
437- * vacuuming before connecting to it. Perhaps look through the pgstats
438- * data for the database's tables? One idea is to keep track of the
439- * number of new and dead tuples per database in pgstats. However it
440- * isn't clear how to construct a metric that measures that and not cause
441- * starvation for less busy databases.
442- */
443- db = NULL ;
444- for_xid_wrap = false;
445- foreach (cell , dblist )
446- {
447- autovac_dbase * tmp = lfirst (cell );
448-
449- /* Find pgstat entry if any */
450- tmp -> entry = pgstat_fetch_stat_dbentry (tmp -> oid );
451-
452- /* Check to see if this one is at risk of wraparound */
453- if (TransactionIdPrecedes (tmp -> frozenxid , xidForceLimit ))
454- {
455- if (db == NULL ||
456- TransactionIdPrecedes (tmp -> frozenxid , db -> frozenxid ))
457- db = tmp ;
458- for_xid_wrap = true;
459- continue ;
460- }
461- else if (for_xid_wrap )
462- continue ; /* ignore not-at-risk DBs */
463-
464- /*
465- * Otherwise, skip a database with no pgstat entry; it means it
466- * hasn't seen any activity.
467- */
468- if (!tmp -> entry )
469- continue ;
470-
471- /*
472- * Remember the db with oldest autovac time. (If we are here,
473- * both tmp->entry and db->entry must be non-null.)
474- */
475- if (db == NULL ||
476- tmp -> entry -> last_autovac_time < db -> entry -> last_autovac_time )
477- db = tmp ;
478- }
479-
480- /* Found a database -- process it */
481- if (db != NULL )
482- {
483- LWLockAcquire (AutovacuumLock , LW_EXCLUSIVE );
484- AutoVacuumShmem -> process_db = db -> oid ;
485- LWLockRelease (AutovacuumLock );
486-
487- SendPostmasterSignal (PMSIGNAL_START_AUTOVAC_WORKER );
488- }
489-
490408sleep :
491409 /*
492410 * in emergency mode, exit immediately so that the postmaster can
@@ -512,6 +430,103 @@ AutoVacLauncherMain(int argc, char *argv[])
512430 proc_exit (0 ); /* done */
513431}
514432
433+ /*
434+ * do_start_worker
435+ *
436+ * Bare-bones procedure for starting an autovacuum worker from the launcher.
437+ * It determines what database to work on, sets up shared memory stuff and
438+ * signals postmaster to start the worker.
439+ */
440+ static void
441+ do_start_worker (void )
442+ {
443+ List * dblist ;
444+ bool for_xid_wrap ;
445+ autovac_dbase * db ;
446+ ListCell * cell ;
447+ TransactionId xidForceLimit ;
448+
449+ /* Get a list of databases */
450+ dblist = autovac_get_database_list ();
451+
452+ /*
453+ * Determine the oldest datfrozenxid/relfrozenxid that we will allow
454+ * to pass without forcing a vacuum. (This limit can be tightened for
455+ * particular tables, but not loosened.)
456+ */
457+ recentXid = ReadNewTransactionId ();
458+ xidForceLimit = recentXid - autovacuum_freeze_max_age ;
459+ /* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */
460+ if (xidForceLimit < FirstNormalTransactionId )
461+ xidForceLimit -= FirstNormalTransactionId ;
462+
463+ /*
464+ * Choose a database to connect to. We pick the database that was least
465+ * recently auto-vacuumed, or one that needs vacuuming to prevent Xid
466+ * wraparound-related data loss. If any db at risk of wraparound is
467+ * found, we pick the one with oldest datfrozenxid, independently of
468+ * autovacuum times.
469+ *
470+ * Note that a database with no stats entry is not considered, except for
471+ * Xid wraparound purposes. The theory is that if no one has ever
472+ * connected to it since the stats were last initialized, it doesn't need
473+ * vacuuming.
474+ *
475+ * XXX This could be improved if we had more info about whether it needs
476+ * vacuuming before connecting to it. Perhaps look through the pgstats
477+ * data for the database's tables? One idea is to keep track of the
478+ * number of new and dead tuples per database in pgstats. However it
479+ * isn't clear how to construct a metric that measures that and not cause
480+ * starvation for less busy databases.
481+ */
482+ db = NULL ;
483+ for_xid_wrap = false;
484+ foreach (cell , dblist )
485+ {
486+ autovac_dbase * tmp = lfirst (cell );
487+
488+ /* Find pgstat entry if any */
489+ tmp -> entry = pgstat_fetch_stat_dbentry (tmp -> oid );
490+
491+ /* Check to see if this one is at risk of wraparound */
492+ if (TransactionIdPrecedes (tmp -> frozenxid , xidForceLimit ))
493+ {
494+ if (db == NULL ||
495+ TransactionIdPrecedes (tmp -> frozenxid , db -> frozenxid ))
496+ db = tmp ;
497+ for_xid_wrap = true;
498+ continue ;
499+ }
500+ else if (for_xid_wrap )
501+ continue ; /* ignore not-at-risk DBs */
502+
503+ /*
504+ * Otherwise, skip a database with no pgstat entry; it means it
505+ * hasn't seen any activity.
506+ */
507+ if (!tmp -> entry )
508+ continue ;
509+
510+ /*
511+ * Remember the db with oldest autovac time. (If we are here,
512+ * both tmp->entry and db->entry must be non-null.)
513+ */
514+ if (db == NULL ||
515+ tmp -> entry -> last_autovac_time < db -> entry -> last_autovac_time )
516+ db = tmp ;
517+ }
518+
519+ /* Found a database -- process it */
520+ if (db != NULL )
521+ {
522+ LWLockAcquire (AutovacuumLock , LW_EXCLUSIVE );
523+ AutoVacuumShmem -> process_db = db -> oid ;
524+ LWLockRelease (AutovacuumLock );
525+
526+ SendPostmasterSignal (PMSIGNAL_START_AUTOVAC_WORKER );
527+ }
528+ }
529+
515530/* SIGHUP: set flag to re-read config file at next convenient time */
516531static void
517532avl_sighup_handler (SIGNAL_ARGS )
0 commit comments