diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
index 298c011..040801b 100644
--- a/core/lib/Drupal/Core/Database/Database.php
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -338,8 +338,8 @@ abstract class Database {
    */
   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 {
@@ -406,9 +406,22 @@ abstract class Database {
     }
     // 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/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
index fbbff42..2ba6b3f 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -24,11 +24,11 @@ use PDO;
 class Connection 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.
@@ -126,36 +126,33 @@ class Connection extends DatabaseConnection {
       $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 (DatabaseException $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 (DatabaseException $e) {
+      }
     }
   }
 
