diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 3465403..a71f4c7 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -210,7 +210,12 @@ public function deleteMultiple(array $cids) {
       while (count($cids));
     }
     catch (\Exception $e) {
-      $this->catchException($e);
+      // Create the cache table, which will be empty. This fixes cases during
+      // core install where a cache table is cleared before it is set
+      // with {cache_block} and {cache_menu}.
+      if (!$this->ensureBinExists()) {
+        $this->catchException($e);
+      }
     }
   }
 
@@ -242,7 +247,12 @@ public function deleteAll() {
       $this->connection->truncate($this->bin)->execute();
     }
     catch (\Exception $e) {
-      $this->catchException($e);
+      // Create the cache table, which will be empty. This fixes cases during
+      // core install where a cache table is cleared before it is set
+      // with {cache_block} and {cache_menu}.
+      if (!$this->ensureBinExists()) {
+        $this->catchException($e);
+      }
     }
   }
 
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
index 9b9cf97..0176e10 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
@@ -31,6 +31,13 @@ class Connection extends DatabaseConnection {
   const DATABASE_NOT_FOUND = 7;
 
   /**
+   * Last used cursor number.
+   *
+   * @var type int
+   */
+  private $_cursor_ctr;
+
+  /**
    * Constructs a connection object.
    */
   public function __construct(\PDO $connection, array $connection_options) {
@@ -52,6 +59,8 @@ public function __construct(\PDO $connection, array $connection_options) {
     if (isset($connection_options['init_commands'])) {
       $this->connection->exec(implode('; ', $connection_options['init_commands']));
     }
+
+    $this->_cursor_ctr = 0;
   }
 
   /**
@@ -128,11 +137,16 @@ public function query($query, array $args = array(), $options = array()) {
         $stmt->execute($args, $options);
       }
 
+      if (strpos($stmt->queryString,'SAVEPOINT mimic_innodb_not_released;') !== FALSE) {
+        $this->connection->prepare("RELEASE SAVEPOINT mimic_innodb_not_released")->execute();
+      }
+
       switch ($options['return']) {
         case Database::RETURN_STATEMENT:
           $stmt->allowRowCount = FALSE;
           return $stmt;
         case Database::RETURN_AFFECTED:
+          $stmt->allowRowCount = TRUE;
           return $stmt->rowCount();
         case Database::RETURN_INSERT_ID:
           return $this->connection->lastInsertId($options['sequence_name']);
@@ -143,6 +157,10 @@ public function query($query, array $args = array(), $options = array()) {
       }
     }
     catch (\PDOException $e) {
+      if (preg_match("/SAVEPOINT (mimic_innodb_(released|not_released))/",$stmt->queryString,$matches)) {
+        $this->connection->prepare("ROLLBACK TO SAVEPOINT " . $matches[1])->execute();
+      }
+
       if ($options['throw_exception']) {
         // Match all SQLSTATE 23xxx errors.
         if (substr($e->getCode(), -6, -3) == '23') {
@@ -170,7 +188,27 @@ public function prepareQuery($query) {
     // @todo This workaround only affects bytea fields, but the involved field
     //   types involved in the query are unknown, so there is no way to
     //   conditionally execute this for affected queries only.
-    return parent::prepareQuery(preg_replace('/ ([^ ]+) +(I*LIKE|NOT +I*LIKE) /i', ' ${1}::text ${2} ', $query));
+    $query = preg_replace('/ ([^ ]+) +(I*LIKE|NOT +I*LIKE) /i', ' ${1}::text ${2} ', $query);
+
+    // While in transaction context, put a SAVEPOINT around every query that isn't
+    // itself a SAVEPOINT operation.  This means that a failed query can't cause
+    // the transaction to abort, which mimics the behavior of innodb.
+    if ($this->inTransaction() &&
+            (stripos($query,'SAVEPOINT ') === FALSE) &&
+            (stripos($query,'RELEASE ') === FALSE)) {
+      if (preg_match('/^[\s]*SELECT /i', $query)) {
+        // In the case of SELECT the SAVEPOINT can also be released in the same
+        // query.  Otherwise the RELEASE is a separate query.
+        $csr = 'csr' . $this->_cursor_ctr++;
+        $query = 'SAVEPOINT mimic_innodb_released; DECLARE '. $csr .' CURSOR FOR ' .
+                 $query . '; RELEASE SAVEPOINT mimic_innodb_released; FETCH ALL ' . $csr;
+      }
+      else {
+        $query = 'SAVEPOINT mimic_innodb_not_released; ' . $query;
+      }
+    }
+
+    return parent::prepareQuery($query);
   }
 
   public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index 8b4f913..5f33415 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -130,7 +130,7 @@ protected function createTableSql($name, $table) {
 
     $sql_keys = array();
     if (isset($table['primary key']) && is_array($table['primary key'])) {
-      $sql_keys[] = 'PRIMARY KEY (' . implode(', ', $table['primary key']) . ')';
+      $sql_keys[] = 'PRIMARY KEY (' . $this->_createPrimaryKeySql($table['primary key']) . ')';
     }
     if (isset($table['unique keys']) && is_array($table['unique keys'])) {
       foreach ($table['unique keys'] as $key_name => $key) {
@@ -318,6 +318,21 @@ protected function _createKeySql($fields) {
     return implode(', ', $return);
   }
 
+  protected function _createPrimaryKeySql($fields) {
+    $return = array();
+    foreach ($fields as $field) {
+      if (is_array($field)) {
+        // Postgresql does not support key length. It does support fillfactor,
+        // but that requires a db lookup for each column.
+        $return[] = '"' . $field[0] . '"';
+      }
+      else {
+        $return[] = '"' . $field . '"';
+      }
+    }
+    return implode(', ', $return);
+  }
+
   function renameTable($table, $new_name) {
     if (!$this->tableExists($table)) {
       throw new SchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
@@ -457,7 +472,7 @@ public function addPrimaryKey($table, $fields) {
       throw new SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode(',', $fields) . ')');
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this->_createPrimaryKeySql($fields) . ')');
   }
 
   public function dropPrimaryKey($table) {
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
index bf9f23a..9963969 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
@@ -55,6 +55,10 @@ public function orderBy($field, $direction = 'ASC') {
     // Call parent function to order on this.
     $return = parent::orderBy($field, $direction);
 
+    if ($this->hasTag('pgsql_no_addfield_on_orderby')) {
+      return $return;
+    }
+
     // If there is a table alias specified, split it up.
     if (strpos($field, '.') !== FALSE) {
       list($table, $table_field) = explode('.', $field);
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
index 5c93433..9fef61c 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php
@@ -65,8 +65,7 @@ public function execute() {
 
     $options = $this->queryOptions;
     $options['already_prepared'] = TRUE;
-    $this->connection->query($stmt, $options);
 
-    return $stmt->rowCount();
+    return $this->connection->query($stmt, array(), $options);
   }
 }
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Query.php b/core/lib/Drupal/Core/Entity/Query/Sql/Query.php
index f5c84b4..e7179c4 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Query.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Query.php
@@ -206,6 +206,7 @@ protected function addSort() {
     }
     // Now we know whether this is a simple query or not, actually do the
     // sorting.
+    $this->sqlQuery->addTag('pgsql_no_addfield_on_orderby');
     foreach ($sort as $key => $sql_alias) {
       $direction = $this->sort[$key]['direction'];
       if ($simple_query || isset($this->sqlGroupBy[$sql_alias])) {
