diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
index 94a23fb..dd4c0a2 100644
--- a/core/lib/Drupal/Core/Database/Connection.php
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -135,6 +135,8 @@
    */
   protected $prefixReplace = array();
 
+  protected $classReferences = array();
+
   function __construct($dsn, $username, $password, $driver_options = array()) {
     // Initialize and prepare the connection prefix.
     $this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
@@ -145,12 +147,29 @@ function __construct($dsn, $username, $password, $driver_options = array()) {
     // Call PDO::__construct and PDO::setAttribute.
     parent::__construct($dsn, $username, $password, $driver_options);
 
-    // Set a specific PDOStatement class if the driver requires that.
+    // Set a Statement class, unless the driver opted out.
     if (!empty($this->statementClass)) {
       $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
     }
   }
 
+  public function addClassReference($object) {
+    $this->classReferences[] = $object;
+  }
+
+  public function destroy() {
+    $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array()));
+
+    // Destroy all references to this connection in other classes by setting
+    // them to NULL. Prevent introducing new references in the local scope by
+    // iterating over array_keys().
+//    debug(count($this->classReferences), '$this->classReferences');
+    foreach (array_keys($this->classReferences) as $i) {
+//      debug(get_class($this->classReferences[$i]));
+      $this->classReferences[$i] = NULL;
+    }
+  }
+
   /**
    * Returns the default query options for any given query.
    *
diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
index 6a425de..35f0df5 100644
--- a/core/lib/Drupal/Core/Database/Database.php
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -338,8 +338,8 @@ public static function addConnectionInfo($key, $target, $info) {
    */
   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 {
@@ -402,11 +402,17 @@ public static function closeConnection($target = NULL, $key = NULL) {
     if (!isset($key)) {
       $key = self::$activeKey;
     }
-    // To close the connection, we need to unset the static variable.
+    // To close a connection, it needs to be set to NULL and removed from the
+    // static variable.
     if (isset($target)) {
+      self::$connections[$key][$target]->destroy();
+      self::$connections[$key][$target] = NULL;
       unset(self::$connections[$key][$target]);
     }
     else {
+      foreach (self::$connections[$key] as $target => $connection) {
+        self::closeConnection($target, $key);
+      }
       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..ae24176 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 @@
 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.
@@ -89,6 +89,12 @@ public function __construct(array $connection_options = array()) {
     $this->exec(implode('; ', $connection_options['init_commands']));
   }
 
+  public function __destruct() {
+    if ($this->needsCleanup) {
+      $this->nextIdDelete();
+    }
+  }
+
   public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
     return $this->query($query . ' LIMIT ' . (int) $from . ', ' . (int) $count, $args, $options);
   }
@@ -126,12 +132,7 @@ public function nextId($existing_id = 0) {
       $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;
   }
 
diff --git a/core/lib/Drupal/Core/Database/Query/Query.php b/core/lib/Drupal/Core/Database/Query/Query.php
index 95ab4b9..ab88fdc 100644
--- a/core/lib/Drupal/Core/Database/Query/Query.php
+++ b/core/lib/Drupal/Core/Database/Query/Query.php
@@ -75,6 +75,7 @@ public function __construct(Connection $connection, $options) {
     $this->uniqueIdentifier = uniqid('', TRUE);
 
     $this->connection = $connection;
+    $this->connection->addClassReference($this);
     $this->connectionKey = $this->connection->getKey();
     $this->connectionTarget = $this->connection->getTarget();
 
diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php
index 2d3159c..343a4f7 100644
--- a/core/lib/Drupal/Core/Database/Query/Select.php
+++ b/core/lib/Drupal/Core/Database/Query/Select.php
@@ -230,7 +230,7 @@ public function compile(Connection $connection, PlaceholderInterface $queryPlace
     $this->having->compile($connection, $queryPlaceholder);
 
     foreach ($this->tables as $table) {
-      // If this table is a subquery, compile it recursively.
+      // If this table is a subquery, compile it recursively.  (reference?)
       if ($table['table'] instanceof SelectInterface) {
         $table['table']->compile($connection, $queryPlaceholder);
       }
diff --git a/core/lib/Drupal/Core/Database/Query/SelectExtender.php b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
index 2f27d1b..b413c4f 100644
--- a/core/lib/Drupal/Core/Database/Query/SelectExtender.php
+++ b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
@@ -42,6 +42,7 @@ public function __construct(SelectInterface $query, Connection $connection) {
     $this->uniqueIdentifier = uniqid('', TRUE);
     $this->query = $query;
     $this->connection = $connection;
+//    $this->connection->addClassReference($this);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 7618a7c..84495ce 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -193,6 +193,7 @@
   public function __construct($connection) {
     $this->uniqueIdentifier = uniqid('', TRUE);
     $this->connection = $connection;
+    $this->connection->addClassReference($this);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Database/Statement.php b/core/lib/Drupal/Core/Database/Statement.php
index c5b1735..21eaee9 100644
--- a/core/lib/Drupal/Core/Database/Statement.php
+++ b/core/lib/Drupal/Core/Database/Statement.php
@@ -34,6 +34,7 @@ class Statement extends PDOStatement implements StatementInterface {
 
   protected function __construct($dbh) {
     $this->dbh = $dbh;
+    $this->dbh->addClassReference($this);
     $this->setFetchMode(PDO::FETCH_OBJ);
   }
 
diff --git a/core/lib/Drupal/Core/Database/StatementPrefetch.php b/core/lib/Drupal/Core/Database/StatementPrefetch.php
index 18dd582..e65dc43 100644
--- a/core/lib/Drupal/Core/Database/StatementPrefetch.php
+++ b/core/lib/Drupal/Core/Database/StatementPrefetch.php
@@ -126,6 +126,7 @@ class StatementPrefetch implements Iterator, StatementInterface {
 
   public function __construct(Connection $connection, $query, array $driver_options = array()) {
     $this->dbh = $connection;
+//    $this->dbh->addClassReference($this);
     $this->queryString = $query;
     $this->driverOptions = $driver_options;
   }
diff --git a/core/lib/Drupal/Core/Database/Transaction.php b/core/lib/Drupal/Core/Database/Transaction.php
index 10adadb..1790cb3 100644
--- a/core/lib/Drupal/Core/Database/Transaction.php
+++ b/core/lib/Drupal/Core/Database/Transaction.php
@@ -50,8 +50,9 @@ class Transaction {
    */
   protected $name;
 
-  public function __construct(Connection &$connection, $name = NULL) {
-    $this->connection = &$connection;
+  public function __construct(Connection $connection, $name = NULL) {
+    $this->connection = $connection;
+//    $this->connection->addClassReference($this);
     // If there is no transaction depth, then no transaction has started. Name
     // the transaction 'drupal_transaction'.
     if (!$depth = $connection->transactionDepth()) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php
new file mode 100644
index 0000000..cd72f26
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php
@@ -0,0 +1,171 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\system\Tests\Database\ConnectionUnitTest.
+ */
+
+namespace Drupal\system\Tests\Database;
+
+use Drupal\Core\Database\Database;
+use Drupal\simpletest\UnitTestBase;
+
+/**
+ * Tests management of database connections.
+ */
+class ConnectionUnitTest extends UnitTestBase {
+
+  protected $key;
+  protected $target;
+  protected $originalCount;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Connection unit tests',
+      'description' => 'Tests management of database connections.',
+      'group' => 'Database',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $this->key = 'default';
+    $this->originalTarget = 'default';
+    $this->target = 'DatabaseConnectionUnitTest';
+
+    // Retrieve current/original amount of connections.
+    $this->originalCount = $this->countConnections();
+  }
+
+  function tearDown() {
+    parent::tearDown();
+  }
+
+  protected function countConnections() {
+    return count(Database::getConnection()->query('SHOW PROCESSLIST')->fetchCol());
+  }
+
+  protected function addConnection() {
+    // Add a new target to the connection, by cloning the current connection.
+    $connection_info = Database::getConnectionInfo($this->key);
+    Database::addConnectionInfo($this->key, $this->target, $connection_info[$this->originalTarget]);
+
+    // Verify that the new target exists.
+    $info = Database::getConnectionInfo($this->key);
+    // Note: Custom assertion message to not expose database credentials.
+    $this->assertIdentical($info[$this->target], $connection_info[$this->key], 'New connection info found.');
+  }
+
+  function testNoop() {
+    // Verify that retrieving the amount again does not increase it.
+    $this->assertIdentical($this->countConnections(), $this->originalCount);
+  }
+
+  /**
+   * Tests Database::closeConnection().
+   */
+  function testOpenClose() {
+    // Add and open a new connection.
+    $this->addConnection();
+    Database::getConnection($this->target, $this->key);
+
+    // Verify that there is a new connection.
+    $this->assertIdentical($this->countConnections(), $this->originalCount + 1);
+
+    // Close the connection.
+    Database::closeConnection($this->target, $this->key);
+    // Wait 20ms to give the database engine sufficient time to react.
+    usleep(20000);
+
+    // Verify that we are back to the original connection count.
+    $this->assertIdentical($this->countConnections(), $this->originalCount);
+  }
+
+  /**
+   * Tests Database::closeConnection().
+   */
+  function testOpenQueryClose() {
+    // Add and open a new connection.
+    $this->addConnection();
+    Database::getConnection($this->target, $this->key);
+
+    // Verify that there is a new connection.
+    $this->assertIdentical($this->countConnections(), $this->originalCount + 1);
+
+    // Execute a query.
+    Database::getConnection($this->target, $this->key)->query('SHOW TABLES');
+
+    // Close the connection.
+    Database::closeConnection($this->target, $this->key);
+    // Wait 20ms to give the database engine sufficient time to react.
+    usleep(20000);
+
+    // Verify that we are back to the original connection count.
+    $this->assertIdentical($this->countConnections(), $this->originalCount);
+  }
+
+  /**
+   * Tests Database::closeConnection().
+   */
+  function testOpenQueryPrefetchClose() {
+    // Add and open a new connection.
+    $this->addConnection();
+    Database::getConnection($this->target, $this->key);
+
+    // Verify that there is a new connection.
+    $this->assertIdentical($this->countConnections(), $this->originalCount + 1);
+
+    // Execute a query.
+    Database::getConnection($this->target, $this->key)->query('SHOW TABLES')->fetchCol();
+
+    // Close the connection.
+    Database::closeConnection($this->target, $this->key);
+    // Wait 20ms to give the database engine sufficient time to react.
+    usleep(20000);
+
+    // Verify that we are back to the original connection count.
+    $this->assertIdentical($this->countConnections(), $this->originalCount);
+  }
+
+  /**
+   * Tests Database::closeConnection().
+   */
+  function testOpenSelectQueryClose() {
+    // Add and open a new connection.
+    $this->addConnection();
+    Database::getConnection($this->target, $this->key);
+
+    // Verify that there is a new connection.
+    $this->assertIdentical($this->countConnections(), $this->originalCount + 1);
+
+    // Create a table.
+    $name = 'foo';
+    Database::getConnection($this->target, $this->key)->schema()->createTable($name, array(
+      'fields' => array(
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 255,
+        ),
+      ),
+    ));
+
+    // Execute a query.
+    Database::getConnection($this->target, $this->key)->select('foo', 'f')
+      ->fields('f', array('name'))
+      ->execute()
+      ->fetchAll();
+
+    // Drop the table.
+    Database::getConnection($this->target, $this->key)->schema()->dropTable($name);
+
+    // Close the connection.
+    Database::closeConnection($this->target, $this->key);
+    // Wait 20ms to give the database engine sufficient time to react.
+    usleep(20000);
+
+    // Verify that we are back to the original connection count.
+    $this->assertIdentical($this->countConnections(), $this->originalCount);
+  }
+
+}
