aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/dbcommands.c33
-rw-r--r--src/backend/storage/ipc/procarray.c28
-rw-r--r--src/include/storage/procarray.h3
3 files changed, 48 insertions, 16 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index d2e38f631f8..846f59244b4 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.230 2010/01/02 16:57:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.231 2010/01/10 15:44:28 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1945,22 +1945,27 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
if (InHotStandby)
{
- VirtualTransactionId *database_users;
-
/*
- * Find all users connected to this database and ask them
- * politely to immediately kill their sessions before processing
- * the drop database record, after the usual grace period.
- * We don't wait for commit because drop database is
- * non-transactional.
+ * We don't do ResolveRecoveryConflictWithVirutalXIDs() here since
+ * that only waits for transactions and completely idle sessions
+ * would block us. This is rare enough that we do this as simply
+ * as possible: no wait, just force them off immediately.
+ *
+ * No locking is required here because we already acquired
+ * AccessExclusiveLock. Anybody trying to connect while we do this
+ * will block during InitPostgres() and then disconnect when they
+ * see the database has been removed.
*/
- database_users = GetConflictingVirtualXIDs(InvalidTransactionId,
- xlrec->db_id,
- false);
+ while (CountDBBackends(xlrec->db_id) > 0)
+ {
+ CancelDBBackends(xlrec->db_id);
- ResolveRecoveryConflictWithVirtualXIDs(database_users,
- "drop database",
- CONFLICT_MODE_FATAL);
+ /*
+ * Wait awhile for them to die so that we avoid flooding an
+ * unresponsive backend when system is heavily loaded.
+ */
+ pg_usleep(10000);
+ }
}
/* Drop pages for this database that are in the shared buffer cache */
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index ccaf8420f5d..01a7c2123f1 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.54 2010/01/02 16:57:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.55 2010/01/10 15:44:28 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1827,6 +1827,32 @@ CountDBBackends(Oid databaseid)
}
/*
+ * CancelDBBackends --- cancel backends that are using specified database
+ */
+void
+CancelDBBackends(Oid databaseid)
+{
+ ProcArrayStruct *arrayP = procArray;
+ int index;
+
+ /* tell all backends to die */
+ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
+ for (index = 0; index < arrayP->numProcs; index++)
+ {
+ volatile PGPROC *proc = arrayP->procs[index];
+
+ if (proc->databaseId == databaseid)
+ {
+ proc->recoveryConflictMode = CONFLICT_MODE_FATAL;
+ kill(proc->pid, SIGINT);
+ }
+ }
+
+ LWLockRelease(ProcArrayLock);
+}
+
+/*
* CountUserBackends --- count backends that are used by specified user
*/
int
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 2a12a83bd08..4572f489af8 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.28 2010/01/02 16:58:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.29 2010/01/10 15:44:28 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -63,6 +63,7 @@ extern pid_t CancelVirtualTransaction(VirtualTransactionId vxid,
extern int CountActiveBackends(void);
extern int CountDBBackends(Oid databaseid);
+extern void CancelDBBackends(Oid databaseid);
extern int CountUserBackends(Oid roleid);
extern bool CountOtherDBBackends(Oid databaseId,
int *nbackends, int *nprepared);