]> granicus.if.org Git - postgresql/commitdiff
Arrange for autovacuum to be killed when another operation wants to be alone
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 16 Jan 2007 13:28:57 +0000 (13:28 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 16 Jan 2007 13:28:57 +0000 (13:28 +0000)
accessing it, like DROP DATABASE.  This allows the regression tests to pass
with autovacuum enabled, which open the gates for finally enabling autovacuum
by default.

src/backend/access/transam/twophase.c
src/backend/commands/dbcommands.c
src/backend/postmaster/autovacuum.c
src/backend/postmaster/postmaster.c
src/backend/storage/ipc/procarray.c
src/backend/storage/lmgr/proc.c
src/include/postmaster/autovacuum.h
src/include/storage/proc.h
src/include/storage/procarray.h

index 4026daa54a278f73cf4a9346d6c278606ee6eb7d..45220d119642c033e9c56f8ed017577ba1ffd66f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *             $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.26 2007/01/05 22:19:23 momjian Exp $
+ *             $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.27 2007/01/16 13:28:56 alvherre Exp $
  *
  * NOTES
  *             Each global transaction is associated with a global transaction
@@ -280,6 +280,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
        gxact->proc.databaseId = databaseid;
        gxact->proc.roleId = owner;
        gxact->proc.inVacuum = false;
+       gxact->proc.isAutovacuum = false;
        gxact->proc.lwWaiting = false;
        gxact->proc.lwExclusive = false;
        gxact->proc.lwWaitLink = NULL;
index ef0aff99ac8b00c4844024861a106cbfea551aa0..18340481d238175d8294641e7d08323aa2ccb1f9 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.188 2007/01/05 22:19:25 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.189 2007/01/16 13:28:56 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -250,11 +250,11 @@ createdb(const CreatedbStmt *stmt)
         * (exception is to allow CREATE DB while connected to template1).
         * Otherwise we might copy inconsistent data.
         */
-       if (DatabaseHasActiveBackends(src_dboid, true))
+       if (DatabaseCancelAutovacuumActivity(src_dboid, true))
                ereport(ERROR,
                                (errcode(ERRCODE_OBJECT_IN_USE),
-                       errmsg("source database \"%s\" is being accessed by other users",
-                                  dbtemplate)));
+                                errmsg("source database \"%s\" is being accessed by other users",
+                                               dbtemplate)));
 
        /* If encoding is defaulted, use source's encoding */
        if (encoding < 0)
@@ -602,7 +602,7 @@ dropdb(const char *dbname, bool missing_ok)
         * Check for active backends in the target database.  (Because we hold the
         * database lock, no new ones can start after this.)
         */
-       if (DatabaseHasActiveBackends(db_id, false))
+       if (DatabaseCancelAutovacuumActivity(db_id, false))
                ereport(ERROR,
                                (errcode(ERRCODE_OBJECT_IN_USE),
                                 errmsg("database \"%s\" is being accessed by other users",
@@ -706,7 +706,7 @@ RenameDatabase(const char *oldname, const char *newname)
         * Make sure the database does not have active sessions.  This is the same
         * concern as above, but applied to other sessions.
         */
-       if (DatabaseHasActiveBackends(db_id, false))
+       if (DatabaseCancelAutovacuumActivity(db_id, false))
                ereport(ERROR,
                                (errcode(ERRCODE_OBJECT_IN_USE),
                                 errmsg("database \"%s\" is being accessed by other users",
index 8caf7ce9199e441885e7cd8827148b8bade8e3de..130ad45fd8be984bc564c018e2dc1dc6745bf109 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.30 2007/01/05 22:19:36 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.31 2007/01/16 13:28:56 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -216,6 +216,15 @@ autovac_forkexec(void)
 
        return postmaster_forkexec(ac, av);
 }
+
+/*
+ * We need this set from the outside, before InitProcess is called
+ */
+void
+AutovacuumIAm(void)
+{
+       am_autovacuum = true;
+}
 #endif   /* EXEC_BACKEND */
 
 /*
@@ -307,8 +316,8 @@ AutoVacMain(int argc, char *argv[])
                EmitErrorReport();
 
                /*
-                * We can now go away.  Note that because we'll call InitProcess, a
-                * callback will be registered to do ProcKill, which will clean up
+                * We can now go away.  Note that because we called InitProcess, a
+                * callback was registered to do ProcKill, which will clean up
                 * necessary state.
                 */
                proc_exit(0);
index 14ccf5dc1ccc91a0b1b73c1f0050c5f1e2e35222..f4c424c9680b1370e8551452a69a7c28e728aac3 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.507 2007/01/05 22:19:36 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.508 2007/01/16 13:28:56 alvherre Exp $
  *
  * NOTES
  *
@@ -3298,6 +3298,10 @@ SubPostmasterMain(int argc, char *argv[])
                strcmp(argv[1], "--forkboot") == 0)
                PGSharedMemoryReAttach();
 
+       /* autovacuum needs this set before calling InitProcess */
+       if (strcmp(argv[1], "--forkautovac") == 0)
+               AutovacuumIAm();
+
        /*
         * Start our win32 signal implementation. This has to be done after we
         * read the backend variables, because we need to pick up the signal pipe
index b31bdf9b7d37551d8d7ac10510b9d7f28c733548..19e5efa683a5071f3b0f8cb62d9fca9ff8952c62 100644 (file)
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.20 2007/01/05 22:19:38 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.21 2007/01/16 13:28:56 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
+#include <signal.h>
+
 #include "access/subtrans.h"
 #include "access/transam.h"
 #include "access/xact.h"
@@ -678,7 +680,9 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
 }
 
 /*
- * DatabaseHasActiveBackends -- are there any backends running in the given DB
+ * DatabaseCancelAutovacuumActivity -- are there any backends running in the
+ * given DB, apart from autovacuum?  If an autovacuum process is running on the
+ * database, kill it and restart the counting.
  *
  * If 'ignoreMyself' is TRUE, ignore this particular backend while checking
  * for backends in the target database.
@@ -691,11 +695,16 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
  * backend startup.
  */
 bool
-DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
+DatabaseCancelAutovacuumActivity(Oid databaseId, bool ignoreMyself)
 {
-       bool            result = false;
        ProcArrayStruct *arrayP = procArray;
        int                     index;
+       int                     num;
+
+restart:
+       num = 0;
+
+       CHECK_FOR_INTERRUPTS();
 
        LWLockAcquire(ProcArrayLock, LW_SHARED);
 
@@ -708,14 +717,22 @@ DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
                        if (ignoreMyself && proc == MyProc)
                                continue;
 
-                       result = true;
-                       break;
+                       num++;
+
+                       if (proc->isAutovacuum)
+                       {
+                               /* an autovacuum -- kill it and restart */
+                               LWLockRelease(ProcArrayLock);
+                               kill(proc->pid, SIGINT);
+                               pg_usleep(100 * 1000);          /* 100ms */
+                               goto restart;
+                       }
                }
        }
 
        LWLockRelease(ProcArrayLock);
 
-       return result;
+       return (num != 0);
 }
 
 /*
index d4500b5c350bc0f186933484b40403813f5dbb91..6e2a0ce81c4297fd56fddd0ea88ec8be80941647 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.182 2007/01/05 22:19:38 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.183 2007/01/16 13:28:56 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,7 @@
 #include "access/transam.h"
 #include "access/xact.h"
 #include "miscadmin.h"
+#include "postmaster/autovacuum.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
@@ -258,6 +259,7 @@ InitProcess(void)
        MyProc->databaseId = InvalidOid;
        MyProc->roleId = InvalidOid;
        MyProc->inVacuum = false;
+       MyProc->isAutovacuum = IsAutoVacuumProcess();
        MyProc->lwWaiting = false;
        MyProc->lwExclusive = false;
        MyProc->lwWaitLink = NULL;
@@ -390,6 +392,7 @@ InitDummyProcess(void)
        MyProc->databaseId = InvalidOid;
        MyProc->roleId = InvalidOid;
        MyProc->inVacuum = false;
+       MyProc->isAutovacuum = false;
        MyProc->lwWaiting = false;
        MyProc->lwExclusive = false;
        MyProc->lwWaitLink = NULL;
index c232ae3b488df60d5dba6ace223b8ef98f20df85..7b3ad7e55098d5da33381021ec2c8c34aafec8d5 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.6 2007/01/05 22:19:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.7 2007/01/16 13:28:57 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@ extern void autovac_stopped(void);
 
 #ifdef EXEC_BACKEND
 extern void AutoVacMain(int argc, char *argv[]);
+extern void AutovacuumIAm(void);
 #endif
 
 #endif   /* AUTOVACUUM_H */
index a52850fb2190ff9c20583e696d49058fd6f2c862..b86f210fbe850fdf0e8a94d2d481e61fc60d5737 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.92 2007/01/05 22:19:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.93 2007/01/16 13:28:57 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,6 +75,7 @@ struct PGPROC
        Oid                     roleId;                 /* OID of role using this backend */
 
        bool            inVacuum;               /* true if current xact is a LAZY VACUUM */
+       bool            isAutovacuum;   /* true if it's autovacuum */
 
        /* Info about LWLock the process is currently waiting for, if any. */
        bool            lwWaiting;              /* true if waiting for an LW lock */
index 265f4eb0b7c43b6f9c2eb10100bf4bf6bcfe67f6..93e82e436805687c3abc08c7bbc890810ec0182d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.11 2007/01/05 22:19:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.12 2007/01/16 13:28:57 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,7 +29,7 @@ extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum);
 extern PGPROC *BackendPidGetProc(int pid);
 extern int     BackendXidGetPid(TransactionId xid);
 extern bool IsBackendPid(int pid);
-extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself);
+extern bool DatabaseCancelAutovacuumActivity(Oid databaseId, bool ignoreMyself);
 
 extern int     CountActiveBackends(void);
 extern int     CountDBBackends(Oid databaseid);