diff --git a/includes/database/database.inc b/includes/database/database.inc
index 6efe298..e3f5a95 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -1624,8 +1624,8 @@
    */
   final public static function removeConnection($key) {
     if (isset(self::$databaseInfo[$key])) {
+      self::closeConnection(NULL, $key);
       unset(self::$databaseInfo[$key]);
-      unset(self::$connections[$key]);
       return TRUE;
     }
     else {
@@ -1693,9 +1693,22 @@
     }
     // To close the connection, we need to unset the static variable.
     if (isset($target)) {
+      // In DatabaseConnection::__construct(), we self-reference the $this
+      // object in the PDO::ATTR_STATEMENT_CLASS attribute, which prevents the
+      // total deallocation of memory when removing a connection. Remove self-
+      // reference by setting an empty PDO::ATTR_STATEMENT_CLASS.
+      self::$connections[$key][$target]->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DatabaseStatementBase', array()));
+
+      // Then unset the connection to disconnect it.
       unset(self::$connections[$key][$target]);
     }
     else {
+      // Clean up each individual connection within this group.
+      foreach (self::$connections[$key] as $target => $connection) {
+        self::closeConnection($target, $key);
+      }
+
+      // Then remove the whole group, which should now be empty.
       unset(self::$connections[$key]);
     }
   }
diff --git a/includes/database/mysql/database.inc b/includes/database/mysql/database.inc
index 7278a2b..295e40e 100644
--- a/includes/database/mysql/database.inc
+++ b/includes/database/mysql/database.inc
@@ -13,11 +13,11 @@
 class DatabaseConnection_mysql extends DatabaseConnection {
 
   /**
-   * Flag to indicate if we have registered the nextID cleanup function.
+   * Flag to indicate if the cleanup function in __destruct() should run.
    *
    * @var boolean
    */
-  protected $shutdownRegistered = FALSE;
+  protected $needsCleanup = FALSE;
 
   public function __construct(array $connection_options = array()) {
     // This driver defaults to transaction support, except if explicitly passed FALSE.
@@ -115,36 +115,33 @@
       $this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id));
       $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
     }
-    if (!$this->shutdownRegistered) {
-      // Use register_shutdown_function() here to keep the database system
-      // independent of Drupal.
-      register_shutdown_function(array($this, 'nextIdDelete'));
-      $shutdownRegistered = TRUE;
-    }
+    $this->needsCleanup = TRUE;
     return $new_id;
   }
 
-  public function nextIdDelete() {
-    // While we want to clean up the table to keep it up from occupying too
-    // much storage and memory, we must keep the highest value in the table
-    // because InnoDB  uses an in-memory auto-increment counter as long as the
-    // server runs. When the server is stopped and restarted, InnoDB
-    // reinitializes the counter for each table for the first INSERT to the
-    // table based solely on values from the table so deleting all values would
-    // be a problem in this case. Also, TRUNCATE resets the auto increment
-    // counter.
-    try {
-      $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
-      // We know we are using MySQL here, no need for the slower db_delete().
-      $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id));
-    }
-    // During testing, this function is called from shutdown with the
-    // simpletest prefix stored in $this->connection, and those tables are gone
-    // by the time shutdown is called so we need to ignore the database
-    // errors. There is no problem with completely ignoring errors here: if
-    // these queries fail, the sequence will work just fine, just use a bit
-    // more database storage and memory.
-    catch (PDOException $e) {
+  public function __destruct() {
+    if ($this->needsCleanup) {
+      // While we want to clean up the table to keep it up from occupying too
+      // much storage and memory, we must keep the highest value in the table
+      // because InnoDB  uses an in-memory auto-increment counter as long as the
+      // server runs. When the server is stopped and restarted, InnoDB
+      // reinitializes the counter for each table for the first INSERT to the
+      // table based solely on values from the table so deleting all values would
+      // be a problem in this case. Also, TRUNCATE resets the auto increment
+      // counter.
+      try {
+        $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
+        // We know we are using MySQL here, no need for the slower db_delete().
+        $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id));
+      }
+      // During testing, this function is called from shutdown with the
+      // simpletest prefix stored in $this->connection, and those tables are gone
+      // by the time shutdown is called so we need to ignore the database
+      // errors. There is no problem with completely ignoring errors here: if
+      // these queries fail, the sequence will work just fine, just use a bit
+      // more database storage and memory.
+      catch (PDOException $e) {
+      }
     }
   }
 