Commit 5d5f1a79 authored by Tom Lane's avatar Tom Lane

Clean up a number of autovacuum loose ends. Make the stats collector

track shared relations in a separate hashtable, so that operations done
from different databases are counted correctly.  Add proper support for
anti-XID-wraparound vacuuming, even in databases that are never connected
to and so have no stats entries.  Miscellaneous other bug fixes.
Alvaro Herrera, some additional fixes by Tom Lane.
parent 507b758a
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.212 2005/07/29 03:25:53 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.213 2005/07/29 19:29:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -4913,6 +4913,36 @@ GetRedoRecPtr(void)
return RedoRecPtr;
}
/*
* GetRecentNextXid - get the nextXid value saved by the most recent checkpoint
*
* This is currently used only by the autovacuum daemon. To check for
* impending XID wraparound, autovac needs an approximate idea of the current
* XID counter, and it needs it before choosing which DB to attach to, hence
* before it sets up a PGPROC, hence before it can take any LWLocks. But it
* has attached to shared memory, and so we can let it reach into the shared
* ControlFile structure and pull out the last checkpoint nextXID.
*
* Since we don't take any sort of lock, we have to assume that reading a
* TransactionId is atomic ... but that assumption is made elsewhere, too,
* and in any case the worst possible consequence of a bogus result is that
* autovac issues an unnecessary database-wide VACUUM.
*
* Note: we could also choose to read ShmemVariableCache->nextXid in an
* unlocked fashion, thus getting a more up-to-date result; but since that
* changes far more frequently than the controlfile checkpoint copy, it would
* pose a far higher risk of bogus result if we did have a nonatomic-read
* problem.
*
* A (theoretically) completely safe answer is to read the actual pg_control
* file into local process memory, but that certainly seems like overkill.
*/
TransactionId
GetRecentNextXid(void)
{
return ControlFile->checkPointCopy.nextXid;
}
/*
* This must be called ONCE during postmaster or standalone-backend shutdown
*/
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.87 2005/07/14 05:13:39 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.88 2005/07/29 19:30:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -317,7 +317,9 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
* a zero-column table.
*/
if (!vacstmt->vacuum)
pgstat_report_analyze(RelationGetRelid(onerel), 0, 0);
pgstat_report_analyze(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
0, 0);
vac_close_indexes(nindexes, Irel, AccessShareLock);
relation_close(onerel, AccessShareLock);
......@@ -436,8 +438,9 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
}
/* report results to the stats collector, too */
pgstat_report_analyze(RelationGetRelid(onerel), totalrows,
totaldeadrows);
pgstat_report_analyze(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
totalrows, totaldeadrows);
}
/* Done with indexes */
......
......@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.311 2005/07/14 05:13:39 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.312 2005/07/29 19:30:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -41,6 +41,7 @@
#include "tcop/pquery.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/flatfiles.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
......@@ -490,7 +491,7 @@ vacuum(VacuumStmt *vacstmt, List *relids)
* If it was a database-wide VACUUM, print FSM usage statistics
* (we don't make you be superuser to see these).
*/
if (vacstmt->relation == NULL)
if (all_rels)
PrintFreeSpaceMapStatistics(elevel);
/*
......@@ -712,7 +713,7 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
* vac_update_dbstats() -- update statistics for one database
*
* Update the whole-database statistics that are kept in its pg_database
* row.
* row, and the flat-file copy of pg_database.
*
* We violate no-overwrite semantics here by storing new values for the
* statistics columns directly into the tuple that's already on the page.
......@@ -721,8 +722,6 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
*
* This routine is shared by full and lazy VACUUM. Note that it is only
* applied after a database-wide VACUUM operation.
*
* Note that we don't bother to update the flat-file copy of pg_database.
*/
static void
vac_update_dbstats(Oid dbid,
......@@ -768,6 +767,9 @@ vac_update_dbstats(Oid dbid,
heap_endscan(scan);
heap_close(relation, RowExclusiveLock);
/* Mark the flat-file copy of pg_database for update at commit */
database_file_update_needed();
}
......@@ -1165,8 +1167,8 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
vacrelstats->rel_tuples, vacrelstats->hasindex);
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), vacstmt->analyze,
vacrelstats->rel_tuples);
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
vacstmt->analyze, vacrelstats->rel_tuples);
}
......
......@@ -31,7 +31,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.55 2005/07/14 05:13:40 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.56 2005/07/29 19:30:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -182,8 +182,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
hasindex);
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), vacstmt->analyze,
vacrelstats->rel_tuples);
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
vacstmt->analyze, vacrelstats->rel_tuples);
}
......
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.145 2005/07/28 15:30:55 momjian Exp $
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.146 2005/07/29 19:30:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -39,6 +39,7 @@
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
#define atoxid(x) ((TransactionId) strtoul((x), NULL, 10))
/* Max size of username ident server can return */
#define IDENT_USERNAME_MAX 512
......@@ -999,13 +1000,14 @@ load_hba(void)
* dbname: gets database name (must be of size NAMEDATALEN bytes)
* dboid: gets database OID
* dbtablespace: gets database's default tablespace's OID
* dbfrozenxid: gets database's frozen XID
*
* This is not much related to the other functions in hba.c, but we put it
* here because it uses the next_token() infrastructure.
*/
bool
read_pg_database_line(FILE *fp, char *dbname,
Oid *dboid, Oid *dbtablespace)
read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
Oid *dbtablespace, TransactionId *dbfrozenxid)
{
char buf[MAX_TOKEN];
......@@ -1024,10 +1026,10 @@ read_pg_database_line(FILE *fp, char *dbname,
if (!isdigit((unsigned char) buf[0]))
elog(FATAL, "bad data in flat pg_database file");
*dbtablespace = atooid(buf);
/* discard datfrozenxid */
next_token(fp, buf, sizeof(buf));
if (!isdigit((unsigned char) buf[0]))
elog(FATAL, "bad data in flat pg_database file");
*dbfrozenxid = atoxid(buf);
/* expect EOL next */
if (next_token(fp, buf, sizeof(buf)))
elog(FATAL, "bad data in flat pg_database file");
......
This diff is collapsed.
This diff is collapsed.
......@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.460 2005/07/21 03:56:11 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.461 2005/07/29 19:30:04 tgl Exp $
*
* NOTES
*
......@@ -1164,13 +1164,13 @@ ServerLoop(void)
/*
* Wait for something to happen.
*
* We wait at most one minute, to ensure that the other background
* tasks handled below get done even when no requests are
* arriving.
* We wait at most one minute, or the minimum autovacuum delay, to
* ensure that the other background tasks handled below get done
* even when no requests are arriving.
*/
memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
timeout.tv_sec = 60;
timeout.tv_sec = Min(60, autovacuum_naptime);
timeout.tv_usec = 0;
PG_SETMASK(&UnBlockSig);
......@@ -3273,7 +3273,7 @@ SubPostmasterMain(int argc, char *argv[])
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Attached process to shared data structures */
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores(false, 0);
AutoVacMain(argc - 2, argv + 2);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.153 2005/07/14 05:13:41 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.154 2005/07/29 19:30:05 tgl Exp $
*
*
*-------------------------------------------------------------------------
......@@ -78,6 +78,7 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
char *filename;
FILE *db_file;
char thisname[NAMEDATALEN];
TransactionId frozenxid;
filename = database_getflatfilename();
db_file = AllocateFile(filename, "r");
......@@ -86,7 +87,8 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", filename)));
while (read_pg_database_line(db_file, thisname, db_id, db_tablespace))
while (read_pg_database_line(db_file, thisname, db_id,
db_tablespace, &frozenxid))
{
if (strcmp(thisname, name) == 0)
{
......@@ -170,10 +172,11 @@ ReverifyMyDatabase(const char *name)
/*
* Also check that the database is currently allowing connections.
* (We do not enforce this in standalone mode, however, so that there is
* a way to recover from "UPDATE pg_database SET datallowconn = false;")
* a way to recover from "UPDATE pg_database SET datallowconn = false;".
* We do not enforce it for the autovacuum process either.)
*/
dbform = (Form_pg_database) GETSTRUCT(tup);
if (IsUnderPostmaster && !dbform->datallowconn)
if (IsUnderPostmaster && !IsAutoVacuumProcess() && !dbform->datallowconn)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("database \"%s\" is not currently accepting connections",
......
......@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.278 2005/07/25 22:12:33 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.279 2005/07/29 19:30:07 tgl Exp $
*
*--------------------------------------------------------------------
*/
......@@ -1418,7 +1418,7 @@ static struct config_int ConfigureNamesInt[] =
NULL
},
&autovacuum_naptime,
60, 0, INT_MAX, NULL, NULL
60, 1, INT_MAX, NULL, NULL
},
{
{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
......
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.66 2005/07/04 04:51:52 tgl Exp $
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.67 2005/07/29 19:30:08 tgl Exp $
*/
#ifndef XLOG_H
#define XLOG_H
......@@ -165,5 +165,6 @@ extern void InitXLOGAccess(void);
extern void CreateCheckPoint(bool shutdown, bool force);
extern void XLogPutNextOid(Oid nextOid);
extern XLogRecPtr GetRedoRecPtr(void);
extern TransactionId GetRecentNextXid(void);
#endif /* XLOG_H */
......@@ -4,7 +4,7 @@
* Interface to hba.c
*
*
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.38 2005/06/28 05:09:13 tgl Exp $
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.39 2005/07/29 19:30:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -36,7 +36,7 @@ extern void load_ident(void);
extern void load_role(void);
extern int hba_getauthmethod(hbaPort *port);
extern int authident(hbaPort *port);
extern bool read_pg_database_line(FILE *fp, char *dbname,
Oid *dboid, Oid *dbtablespace);
extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
Oid *dbtablespace, TransactionId *dbfrozenxid);
#endif /* HBA_H */
......@@ -5,7 +5,7 @@
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.33 2005/07/14 05:13:43 tgl Exp $
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.34 2005/07/29 19:30:09 tgl Exp $
* ----------
*/
#ifndef PGSTAT_H
......@@ -384,10 +384,11 @@ extern void pgstat_ping(void);
extern void pgstat_report_activity(const char *what);
extern void pgstat_report_tabstat(void);
extern void pgstat_report_autovac(void);
extern void pgstat_report_vacuum(Oid tableoid, bool analyze,
PgStat_Counter tuples);
extern void pgstat_report_analyze(Oid tableoid, PgStat_Counter livetuples,
PgStat_Counter deadtuples);
extern void pgstat_report_vacuum(Oid tableoid, bool shared,
bool analyze, PgStat_Counter tuples);
extern void pgstat_report_analyze(Oid tableoid, bool shared,
PgStat_Counter livetuples,
PgStat_Counter deadtuples);
extern int pgstat_vacuum_tabstat(void);
extern void pgstat_reset_counters(void);
......
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