diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
index 5b160868075d1aa46ec397b5c35ab954ce441d40..064adc2ccab57bd59a32e868aa3b0ee8af93e110 100644
--- a/core/lib/Drupal/Core/Database/Connection.php
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -23,7 +23,7 @@
  *
  * @see http://php.net/manual/book.pdo.php
  */
-abstract class Connection extends PDO {
+abstract class Connection implements \Serializable {
 
   /**
    * The database target this connection is for.
@@ -100,6 +100,13 @@ abstract class Connection extends PDO {
    */
   protected $temporaryNameIndex = 0;
 
+  /**
+   * The actual PDO connection.
+   *
+   * @var \PDO
+   */
+  protected $connection;
+
   /**
    * The connection information for this connection object.
    *
@@ -135,22 +142,33 @@ abstract class Connection extends PDO {
    */
   protected $prefixReplace = array();
 
-  function __construct($dsn, $username, $password, $driver_options = array()) {
+  /**
+   * Constructs a Connection object.
+   */
+  public function __construct(PDO $connection, array $connection_options) {
     // Initialize and prepare the connection prefix.
-    $this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
-
-    // Because the other methods don't seem to work right.
-    $driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
-
-    // Call PDO::__construct and PDO::setAttribute.
-    parent::__construct($dsn, $username, $password, $driver_options);
+    $this->setPrefix(isset($connection_options['prefix']) ? $connection_options['prefix'] : '');
 
     // Set a Statement class, unless the driver opted out.
     if (!empty($this->statementClass)) {
-      $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
+      $connection->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
     }
+
+    $this->connection = $connection;
+    $this->connectionOptions = $connection_options;
   }
 
+  /**
+   * Opens a PDO connection.
+   *
+   * @param array $connection_options
+   *   The database connection settings array.
+   *
+   * @return \PDO
+   *   A \PDO object.
+   */
+  public static function open(array &$connection_options = array()) { }
+
   /**
    * Destroys this Connection object.
    *
@@ -163,7 +181,7 @@ public function destroy() {
     // Destroy all references to this connection by setting them to NULL.
     // The Statement class attribute only accepts a new value that presents a
     // proper callable, so we reset it to PDOStatement.
-    $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array()));
+    $this->connection->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement', array()));
     $this->schema = NULL;
   }
 
@@ -318,8 +336,7 @@ public function tablePrefix($table = 'default') {
   public function prepareQuery($query) {
     $query = $this->prefixTables($query);
 
-    // Call PDO::prepare.
-    return parent::prepare($query);
+    return $this->connection->prepare($query);
   }
 
   /**
@@ -532,7 +549,7 @@ public function query($query, array $args = array(), $options = array()) {
         case Database::RETURN_AFFECTED:
           return $stmt->rowCount();
         case Database::RETURN_INSERT_ID:
-          return $this->lastInsertId();
+          return $this->connection->lastInsertId();
         case Database::RETURN_NULL:
           return;
         default:
@@ -921,7 +938,7 @@ public function rollback($savepoint_name = 'drupal_transaction') {
         $rolled_back_other_active_savepoints = TRUE;
       }
     }
-    parent::rollBack();
+    $this->connection->rollBack();
     if ($rolled_back_other_active_savepoints) {
       throw new TransactionOutOfOrderException();
     }
@@ -949,7 +966,7 @@ public function pushTransaction($name) {
       $this->query('SAVEPOINT ' . $name);
     }
     else {
-      parent::beginTransaction();
+      $this->connection->beginTransaction();
     }
     $this->transactionLayers[$name] = $name;
   }
@@ -1000,7 +1017,7 @@ protected function popCommittableTransactions() {
       // If there are no more layers left then we should commit.
       unset($this->transactionLayers[$name]);
       if (empty($this->transactionLayers)) {
-        if (!parent::commit()) {
+        if (!$this->connection->commit()) {
           throw new TransactionCommitFailedException();
         }
       }
@@ -1084,7 +1101,7 @@ abstract public function driver();
    * Returns the version of the database server.
    */
   public function version() {
-    return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
+    return $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION);
   }
 
   /**
@@ -1178,4 +1195,76 @@ public function commit() {
    *   also larger than the $existing_id if one was passed in.
    */
   abstract public function nextId($existing_id = 0);
+
+  /**
+   * Prepares a statement for execution and returns a statement object
+   *
+   * Emulated prepared statements does not communicate with the database server
+   * so this method does not check the statement.
+   *
+   * @param string $statement
+   *   This must be a valid SQL statement for the target database server.
+   * @param array $driver_options
+   *   (optional) This array holds one or more key=>value pairs to set
+   *   attribute values for the PDOStatement object that this method returns.
+   *   You would most commonly use this to set the \PDO::ATTR_CURSOR value to
+   *   \PDO::CURSOR_SCROLL to request a scrollable cursor. Some drivers have
+   *   driver specific options that may be set at prepare-time. Defaults to an
+   *   empty array.
+   *
+   * @return \PDOStatement|false
+   *   If the database server successfully prepares the statement, returns a
+   *   \PDOStatement object.
+   *   If the database server cannot successfully prepare the statement  returns
+   *   FALSE or emits \PDOException (depending on error handling).
+   *
+   * @throws \PDOException
+   *
+   * @see \PDO::prepare()
+   */
+  public function prepare($statement, array $driver_options = array()) {
+    return $this->connection->prepare($statement, $driver_options);
+  }
+
+  /**
+   * Quotes a string for use in a query.
+   *
+   * @param string $string
+   *   The string to be quoted.
+   * @param int $parameter_type
+   *   (optional) Provides a data type hint for drivers that have alternate
+   *   quoting styles. Defaults to \PDO::PARAM_STR.
+   *
+   * @return string|bool
+   *   A quoted string that is theoretically safe to pass into an SQL statement.
+   *   Returns FALSE if the driver does not support quoting in this way.
+   *
+   * @see \PDO::quote()
+   */
+  public function quote($string, $parameter_type = \PDO::PARAM_STR) {
+    return $this->connection->quote($string, $parameter_type);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function serialize() {
+    $connection = clone $this;
+    // Don't serialize the PDO connection and other lazy-instantiated members.
+    unset($connection->connection, $connection->schema, $connection->driverClasses);
+    return serialize(get_object_vars($connection));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function unserialize($serialized) {
+    $data = unserialize($serialized);
+    foreach ($data as $key => $value) {
+      $this->{$key} = $value;
+    }
+    // Re-establish the PDO connection using the original options.
+    $this->connection = static::open($this->connectionOptions);
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
index a54c9cb5ce5069186e622ee4f433320f461f4a05..d6c28ca39a6e3872acc780496ef99af6b2e0055f 100644
--- a/core/lib/Drupal/Core/Database/Database.php
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -381,7 +381,9 @@ final protected static function openConnection($key, $target) {
       // Fallback for Drupal 7 settings.php.
       $driver_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\Connection";
     }
-    $new_connection = new $driver_class(self::$databaseInfo[$key][$target]);
+
+    $pdo_connection = $driver_class::open(self::$databaseInfo[$key][$target]);
+    $new_connection = new $driver_class($pdo_connection, self::$databaseInfo[$key][$target]);
     $new_connection->setTarget($target);
     $new_connection->setKey($key);
 
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
index 128780ff0a07ec443d26c0ff2dd3c38c1d20dbb3..9e0e65fac34e0a3e091dbf6714410510bee429e1 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
@@ -36,7 +36,12 @@ class Connection extends DatabaseConnection {
    */
   protected $needsCleanup = FALSE;
 
-  public function __construct(array $connection_options = array()) {
+  /**
+   * Constructs a Connection object.
+   */
+  public function __construct(PDO $connection, array $connection_options = array()) {
+    parent::__construct($connection, $connection_options);
+
     // This driver defaults to transaction support, except if explicitly passed FALSE.
     $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
 
@@ -44,7 +49,12 @@ public function __construct(array $connection_options = array()) {
     $this->transactionalDDLSupport = FALSE;
 
     $this->connectionOptions = $connection_options;
+  }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function open(array &$connection_options = array()) {
     // The DSN should use either a socket or a host/port.
     if (isset($connection_options['unix_socket'])) {
       $dsn = 'mysql:unix_socket=' . $connection_options['unix_socket'];
@@ -61,22 +71,23 @@ public function __construct(array $connection_options = array()) {
       'pdo' => array(),
     );
     $connection_options['pdo'] += array(
+      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
       // So we don't have to mess around with cursors and unbuffered queries by default.
       PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
       // Because MySQL's prepared statements skip the query cache, because it's dumb.
       PDO::ATTR_EMULATE_PREPARES => TRUE,
     );
 
-    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
+    $pdo = new PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
 
     // Force MySQL to use the UTF-8 character set. Also set the collation, if a
     // certain one has been set; otherwise, MySQL defaults to 'utf8_general_ci'
     // for UTF-8.
     if (!empty($connection_options['collation'])) {
-      $this->exec('SET NAMES utf8 COLLATE ' . $connection_options['collation']);
+      $pdo->exec('SET NAMES utf8 COLLATE ' . $connection_options['collation']);
     }
     else {
-      $this->exec('SET NAMES utf8');
+      $pdo->exec('SET NAMES utf8');
     }
 
     // Set MySQL init_commands if not already defined.  Default Drupal's MySQL
@@ -94,7 +105,9 @@ public function __construct(array $connection_options = array()) {
       'sql_mode' => "SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'",
     );
     // Set connection options.
-    $this->exec(implode('; ', $connection_options['init_commands']));
+    $pdo->exec(implode('; ', $connection_options['init_commands']));
+
+    return $pdo;
   }
 
   public function __destruct() {
@@ -135,8 +148,8 @@ public function createDatabase($database) {
 
     try {
       // Create the database and set it as active.
-      $this->exec("CREATE DATABASE $database");
-      $this->exec("USE $database");
+      $this->connection->exec("CREATE DATABASE $database");
+      $this->connection->exec("USE $database");
     }
     catch (\Exception $e) {
       throw new DatabaseNotFoundException($e->getMessage());
@@ -204,7 +217,7 @@ protected function popCommittableTransactions() {
       // If there are no more layers left then we should commit.
       unset($this->transactionLayers[$name]);
       if (empty($this->transactionLayers)) {
-        if (!PDO::commit()) {
+        if (!$this->connection->commit()) {
           throw new TransactionCommitFailedException();
         }
       }
@@ -227,7 +240,7 @@ protected function popCommittableTransactions() {
             $this->transactionLayers = array();
             // We also have to explain to PDO that the transaction stack has
             // been cleaned-up.
-            PDO::commit();
+            $this->connection->commit();
           }
           else {
             throw $e;
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
index 4fd7d0d4c803fe1456cbddf2741b4643afb9c504..30e9e010a54cb4944ca1505e6085b778f72b26b5 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
@@ -34,7 +34,12 @@ class Connection extends DatabaseConnection {
    */
   const DATABASE_NOT_FOUND = 7;
 
-  public function __construct(array $connection_options = array()) {
+  /**
+   * Constructs a connection object.
+   */
+  public function __construct(PDO $connection, array $connection_options) {
+    parent::__construct($connection, $connection_options);
+
     // This driver defaults to transaction support, except if explicitly passed FALSE.
     $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
 
@@ -42,6 +47,21 @@ public function __construct(array $connection_options = array()) {
     // but we'll only enable it if standard transactions are.
     $this->transactionalDDLSupport = $this->transactionSupport;
 
+    $this->connectionOptions = $connection_options;
+
+    // Force PostgreSQL to use the UTF-8 character set by default.
+    $this->connection->exec("SET NAMES 'UTF8'");
+
+    // Execute PostgreSQL init_commands.
+    if (isset($connection_options['init_commands'])) {
+      $this->connection->exec(implode('; ', $connection_options['init_commands']));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function open(array &$connection_options = array()) {
     // Default to TCP connection on port 5432.
     if (empty($connection_options['port'])) {
       $connection_options['port'] = 5432;
@@ -61,8 +81,6 @@ public function __construct(array $connection_options = array()) {
       $connection_options['password'] = str_replace('\\', '\\\\', $connection_options['password']);
     }
 
-    $this->connectionOptions = $connection_options;
-
     $connection_options['database'] = (!empty($connection_options['database']) ? $connection_options['database'] : 'template1');
     $dsn = 'pgsql:host=' . $connection_options['host'] . ' dbname=' . $connection_options['database'] . ' port=' . $connection_options['port'];
 
@@ -71,6 +89,7 @@ public function __construct(array $connection_options = array()) {
       'pdo' => array(),
     );
     $connection_options['pdo'] += array(
+      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
       // Prepared statements are most effective for performance when queries
       // are recycled (used several times). However, if they are not re-used,
       // prepared statements become ineffecient. Since most of Drupal's
@@ -81,17 +100,12 @@ public function __construct(array $connection_options = array()) {
       // Convert numeric values to strings when fetching.
       PDO::ATTR_STRINGIFY_FETCHES => TRUE,
     );
-    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
+    $pdo = new PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
 
-    // Force PostgreSQL to use the UTF-8 character set by default.
-    $this->exec("SET NAMES 'UTF8'");
-
-    // Execute PostgreSQL init_commands.
-    if (isset($connection_options['init_commands'])) {
-      $this->exec(implode('; ', $connection_options['init_commands']));
-    }
+    return $pdo;
   }
 
+
   public function query($query, array $args = array(), $options = array()) {
 
     $options += $this->defaultOptions();
@@ -124,7 +138,7 @@ public function query($query, array $args = array(), $options = array()) {
         case Database::RETURN_AFFECTED:
           return $stmt->rowCount();
         case Database::RETURN_INSERT_ID:
-          return $this->lastInsertId($options['sequence_name']);
+          return $this->connection->lastInsertId($options['sequence_name']);
         case Database::RETURN_NULL:
           return;
         default:
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
index abda55628d4413c679ae191ed0bf730fb379f391..7d05b1fad682702351f530c7689285dcbdfd2b71 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php
@@ -66,7 +66,12 @@ class Connection extends DatabaseConnection {
    */
   var $tableDropped = FALSE;
 
-  public function __construct(array $connection_options = array()) {
+  /**
+   * Constructs a \Drupal\Core\Database\Driver\sqlite\Connection object.
+   */
+  public function __construct(PDO $connection, array $connection_options) {
+    parent::__construct($connection, $connection_options);
+
     // We don't need a specific PDOStatement class here, we simulate it below.
     $this->statementClass = NULL;
 
@@ -75,16 +80,6 @@ public function __construct(array $connection_options = array()) {
 
     $this->connectionOptions = $connection_options;
 
-    // Allow PDO options to be overridden.
-    $connection_options += array(
-      'pdo' => array(),
-    );
-    $connection_options['pdo'] += array(
-      // Convert numeric values to strings when fetching.
-      PDO::ATTR_STRINGIFY_FETCHES => TRUE,
-    );
-    parent::__construct('sqlite:' . $connection_options['database'], '', '', $connection_options['pdo']);
-
     // Attach one database for each registered prefix.
     $prefixes = $this->prefixes;
     foreach ($prefixes as $table => &$prefix) {
@@ -107,24 +102,43 @@ public function __construct(array $connection_options = array()) {
     // Detect support for SAVEPOINT.
     $version = $this->query('SELECT sqlite_version()')->fetchField();
     $this->savepointSupport = (version_compare($version, '3.6.8') >= 0);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function open(array &$connection_options = array()) {
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
+      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+      // Convert numeric values to strings when fetching.
+      PDO::ATTR_STRINGIFY_FETCHES => TRUE,
+    );
+    $pdo = new PDO('sqlite:' . $connection_options['database'], '', '', $connection_options['pdo']);
 
     // Create functions needed by SQLite.
-    $this->sqliteCreateFunction('if', array($this, 'sqlFunctionIf'));
-    $this->sqliteCreateFunction('greatest', array($this, 'sqlFunctionGreatest'));
-    $this->sqliteCreateFunction('pow', 'pow', 2);
-    $this->sqliteCreateFunction('length', 'strlen', 1);
-    $this->sqliteCreateFunction('md5', 'md5', 1);
-    $this->sqliteCreateFunction('concat', array($this, 'sqlFunctionConcat'));
-    $this->sqliteCreateFunction('substring', array($this, 'sqlFunctionSubstring'), 3);
-    $this->sqliteCreateFunction('substring_index', array($this, 'sqlFunctionSubstringIndex'), 3);
-    $this->sqliteCreateFunction('rand', array($this, 'sqlFunctionRand'));
+    $pdo->sqliteCreateFunction('if', array(__CLASS__, 'sqlFunctionIf'));
+    $pdo->sqliteCreateFunction('greatest', array(__CLASS__, 'sqlFunctionGreatest'));
+    $pdo->sqliteCreateFunction('pow', 'pow', 2);
+    $pdo->sqliteCreateFunction('length', 'strlen', 1);
+    $pdo->sqliteCreateFunction('md5', 'md5', 1);
+    $pdo->sqliteCreateFunction('concat', array(__CLASS__, 'sqlFunctionConcat'));
+    $pdo->sqliteCreateFunction('substring', array(__CLASS__, 'sqlFunctionSubstring'), 3);
+    $pdo->sqliteCreateFunction('substring_index', array(__CLASS__, 'sqlFunctionSubstringIndex'), 3);
+    $pdo->sqliteCreateFunction('rand', array(__CLASS__, 'sqlFunctionRand'));
 
     // Execute sqlite init_commands.
     if (isset($connection_options['init_commands'])) {
-      $this->exec(implode('; ', $connection_options['init_commands']));
+      $pdo->exec(implode('; ', $connection_options['init_commands']));
     }
+
+    return $pdo;
   }
 
+
   /**
    * Destructor for the SQLite connection.
    *
@@ -158,14 +172,14 @@ public function __destruct() {
   /**
    * SQLite compatibility implementation for the IF() SQL function.
    */
-  public function sqlFunctionIf($condition, $expr1, $expr2 = NULL) {
+  public static function sqlFunctionIf($condition, $expr1, $expr2 = NULL) {
     return $condition ? $expr1 : $expr2;
   }
 
   /**
    * SQLite compatibility implementation for the GREATEST() SQL function.
    */
-  public function sqlFunctionGreatest() {
+  public static function sqlFunctionGreatest() {
     $args = func_get_args();
     foreach ($args as $k => $v) {
       if (!isset($v)) {
@@ -183,7 +197,7 @@ public function sqlFunctionGreatest() {
   /**
    * SQLite compatibility implementation for the CONCAT() SQL function.
    */
-  public function sqlFunctionConcat() {
+  public static function sqlFunctionConcat() {
     $args = func_get_args();
     return implode('', $args);
   }
@@ -191,14 +205,14 @@ public function sqlFunctionConcat() {
   /**
    * SQLite compatibility implementation for the SUBSTRING() SQL function.
    */
-  public function sqlFunctionSubstring($string, $from, $length) {
+  public static function sqlFunctionSubstring($string, $from, $length) {
     return substr($string, $from - 1, $length);
   }
 
   /**
    * SQLite compatibility implementation for the SUBSTRING_INDEX() SQL function.
    */
-  public function sqlFunctionSubstringIndex($string, $delimiter, $count) {
+  public static function sqlFunctionSubstringIndex($string, $delimiter, $count) {
     // If string is empty, simply return an empty string.
     if (empty($string)) {
       return '';
@@ -247,7 +261,7 @@ public function prepare($query, $options = array()) {
    * the world.
    */
   public function PDOPrepare($query, array $options = array()) {
-    return parent::prepare($query, $options);
+    return $this->connection->prepare($query, $options);
   }
 
   public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
@@ -354,7 +368,7 @@ public function rollback($savepoint_name = 'drupal_transaction') {
       }
     }
     if ($this->supportsTransactions()) {
-      PDO::rollBack();
+      $this->connection->rollBack();
     }
   }
 
@@ -394,9 +408,9 @@ public function popTransaction($name) {
         // If there was any rollback() we should roll back whole transaction.
         if ($this->willRollback) {
           $this->willRollback = FALSE;
-          PDO::rollBack();
+          $this->connection->rollBack();
         }
-        elseif (!PDO::commit()) {
+        elseif (!$this->connection->commit()) {
           throw new TransactionCommitFailedException();
         }
       }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionTest.php
index 8bdc45e2c820641abb17b7ca3642b1d3efb26038..c20d83d22a0b2015c27da1a5afefa7ed9131fb98 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionTest.php
@@ -123,4 +123,5 @@ function testConnectionOptions() {
     $connectionOptions = $db->getConnectionOptions();
     $this->assertNotEqual($connection_info['default']['database'], $connectionOptions['database'], 'The test connection info database does not match the current connection options database.');
   }
+
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php
index 3bba87008db6924365068ac1af2e9978f067ba95..4bcc54fa27c12d2a16b9a25b075b5f228186078f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/ConnectionUnitTest.php
@@ -226,4 +226,64 @@ function testOpenSelectQueryClose() {
     $this->assertNoConnection($id);
   }
 
+  /**
+   * Tests the serialization and unserialization of a database connection.
+   */
+  public function testConnectionSerialization() {
+    $db = Database::getConnection('default', 'default');
+
+    try {
+      $serialized = serialize($db);
+      $this->pass('The database connection can be serialized.');
+
+      $unserialized = unserialize($serialized);
+      $this->assertTrue(get_class($unserialized) === get_class($db));
+    }
+    catch (\Exception $e) {
+      $this->fail('The database connection cannot be serialized.');
+    }
+
+    // Ensure that all properties on the unserialized object are the same.
+    $db_reflection = new \ReflectionObject($db);
+    $unserialized_reflection = new \ReflectionObject($unserialized);
+    foreach ($db_reflection->getProperties() as $value) {
+      // Skip the pdo connection object.
+      if ($value->getName() == 'connection') {
+        continue;
+      }
+      $value->setAccessible(TRUE);
+      $unserialized_property = $unserialized_reflection->getProperty($value->getName());
+      $unserialized_property->setAccessible(TRUE);
+      $this->assertEqual($unserialized_property->getValue($unserialized), $value->getValue($db));
+    }
+
+  }
+
+  /**
+   * Tests pdo options override.
+   */
+  public function testConnectionOpen() {
+    $connection = Database::getConnection('default');
+    $reflection = new \ReflectionObject($connection);
+    $connection_property = $reflection->getProperty('connection');
+    $connection_property->setAccessible(TRUE);
+    $error_mode = $connection_property->getValue($connection)
+      ->getAttribute(\PDO::ATTR_ERRMODE);
+    $this->assertEqual($error_mode, \PDO::ERRMODE_EXCEPTION, 'Ensure the default error mode is set to exception.');
+
+    $connection = Database::getConnectionInfo('default');
+    $connection['default']['pdo'][\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT;
+    Database::addConnectionInfo('test', 'default', $connection['default']);
+    $connection = Database::getConnection('default', 'test');
+
+    $reflection = new \ReflectionObject($connection);
+    $connection_property = $reflection->getProperty('connection');
+    $connection_property->setAccessible(TRUE);
+    $error_mode = $connection_property->getValue($connection)
+      ->getAttribute(\PDO::ATTR_ERRMODE);
+    $this->assertEqual($error_mode, \PDO::ERRMODE_SILENT, 'Ensure PDO connection options can be overridden.');
+
+    Database::removeConnection('test');
+  }
+
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index c662ec78574dd5c6cd0f2d07d7bc484f321676d1..f402395d5f6d14c396fbabe8e377bf30347c2b27 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -664,4 +664,13 @@ function testMultiFormSameNameErrorClass() {
     $this->assertFieldByXpath('//input[@id="edit-name" and contains(@class, "error")]', NULL, 'Error input form element class found for first element.');
     $this->assertNoFieldByXpath('//input[@id="edit-name--2" and contains(@class, "error")]', NULL, 'No error input form element class found for second element.');
   }
+
+  /**
+   * Tests a form with a form state storing a database connection.
+   */
+  public function testFormStateDatabaseConnection() {
+    $this->assertNoText('Database connection found');
+    $this->drupalPost('form-test/form_state-database', array(), t('Submit'));
+    $this->assertText('Database connection found');
+  }
 }
diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module
index c7a85a3491c8aee248e82575d81760bd499538fc..97657a1f9cba0bb44ae0d92ba0748f1cededb97b 100644
--- a/core/modules/system/tests/modules/form_test/form_test.module
+++ b/core/modules/system/tests/modules/form_test/form_test.module
@@ -5,6 +5,8 @@
  * Helper module for the form API tests.
  */
 
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Database;
 use Drupal\form_test\Callbacks;
 use Drupal\form_test\FormTestObject;
 use Drupal\form_test\SystemConfigFormTestForm;
@@ -353,6 +355,13 @@ function form_test_menu() {
     'access callback' => TRUE,
   );
 
+  $items['form-test/form_state-database'] = array(
+    'title' => t('Form state with a database connection'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('form_test_form_state_database'),
+    'access callback' => TRUE,
+  );
+
   return $items;
 }
 
@@ -2466,3 +2475,40 @@ function form_test_group_vertical_tabs() {
   );
   return $form;
 }
+
+/**
+ * Builds a form which gets the database connection stored in the form state.
+ */
+function form_test_form_state_database($form, &$form_state) {
+  $form['text'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Text field'),
+  );
+
+  $form['test_submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+
+  $db = Database::getConnection('default');
+  $form_state['storage']['database'] = $db;
+  $form_state['storage']['database_class'] = get_class($db);
+
+  if (isset($form_state['storage']['database_connection_found'])) {
+    $form['database']['#markup'] = 'Database connection found';
+  }
+
+  return $form;
+}
+
+/**
+ * Form submit handler for database form_state test.
+ */
+function form_test_form_state_database_submit($form, &$form_state) {
+  $form_state['cache'] = TRUE;
+  $form_state['rebuild'] = TRUE;
+
+  if ($form_state['storage']['database'] instanceof $form_state['storage']['database_class']) {
+    $form_state['storage']['database_connection_found'] = TRUE;
+  }
+}