diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index d4de8bf..ac1fd05 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -95,10 +95,6 @@ class DatabaseBackend implements CacheBackendInterface {
   protected function prepareItem($cache) {
     global $user;
 
-    if (!isset($cache->data)) {
-      return FALSE;
-    }
-
     // The cache data is invalid if any of its tags have been cleared since.
     if ($cache->tags) {
       $cache->tags = explode(' ', $cache->tags);
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index 021b818..d40b9e8 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -80,10 +80,6 @@ class MemoryBackend implements CacheBackendInterface {
    *   valid item to load.
    */
   protected function prepareItem($cache) {
-    if (!isset($cache->data)) {
-      return FALSE;
-    }
-
     // The cache data is invalid if any of its tags have been cleared since.
     if (count($cache->tags) && $this->hasInvalidatedTags($cache)) {
       return FALSE;
diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
index 94a23fb..f377100 100644
--- a/core/lib/Drupal/Core/Database/Connection.php
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -479,13 +479,14 @@ abstract class Connection extends PDO {
    * @return Drupal\Core\Database\StatementInterface
    *   This method will return one of: the executed statement, the number of
    *   rows affected by the query (not the number matched), or the generated
-   *   insert IT of the last query, depending on the value of
+   *   insert ID of the last query, depending on the value of
    *   $options['return']. Typically that value will be set by default or a
    *   query builder and should not be set by a user. If there is an error,
    *   this method will return NULL and may throw an exception if
    *   $options['throw_exception'] is TRUE.
    *
    * @throws PDOException
+   * @throws Drupal\Core\Database\IntegrityConstraintViolationException
    */
   public function query($query, array $args = array(), $options = array()) {
 
@@ -529,7 +530,13 @@ abstract class Connection extends PDO {
         // debug information.
         $query_string = ($query instanceof DatabaseStatementInterface) ? $stmt->getQueryString() : $query;
         $message = $e->getMessage() . ": " . $query_string . "; " . print_r($args, TRUE);
-        $exception = new DatabaseExceptionWrapper($message, 0, $e);
+        // Match all SQLSTATE 23xxx errors.
+        if (substr($e->getCode(), -6, -3) == '23') {
+          $exception = new IntegrityConstraintViolationException($message, $e->getCode(), $e);
+        }
+        else {
+          $exception = new DatabaseExceptionWrapper($message, 0, $e);
+        }
 
         throw $exception;
       }
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
index 91d95ff..76ca82a 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
@@ -10,6 +10,7 @@ namespace Drupal\Core\Database\Driver\pgsql;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\Connection as DatabaseConnection;
 use Drupal\Core\Database\StatementInterface;
+use Drupal\Core\Database\IntegrityConstraintViolationException;
 
 use PDO;
 use PDOException;
@@ -124,6 +125,10 @@ class Connection extends DatabaseConnection {
     }
     catch (PDOException $e) {
       if ($options['throw_exception']) {
+        // Match all SQLSTATE 23xxx errors.
+        if (substr($e->getCode(), -6, -3) == '23') {
+          $e = new IntegrityConstraintViolationException($e->getMessage(), $e->getCode(), $e);
+        }
         // Add additional debug information.
         if ($query instanceof StatementInterface) {
           $e->query_string = $stmt->getQueryString();
diff --git a/core/lib/Drupal/Core/Database/IntegrityConstraintViolationException.php b/core/lib/Drupal/Core/Database/IntegrityConstraintViolationException.php
new file mode 100644
index 0000000..7b8ac43
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/IntegrityConstraintViolationException.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Database\IntegrityConstraintViolationException
+ */
+
+namespace Drupal\Core\Database;
+
+use RuntimeException;
+
+/**
+ * Exception thrown if a query would violate an integrity constraint.
+ *
+ * This exception is thrown e.g. when trying to insert a row that would violate
+ * a unique key constraint.
+ */
+class IntegrityConstraintViolationException extends RuntimeException implements DatabaseException { }
diff --git a/core/lib/Drupal/Core/Database/Query/Merge.php b/core/lib/Drupal/Core/Database/Query/Merge.php
index 547a223..3d7564a 100644
--- a/core/lib/Drupal/Core/Database/Query/Merge.php
+++ b/core/lib/Drupal/Core/Database/Query/Merge.php
@@ -9,6 +9,7 @@ namespace Drupal\Core\Database\Query;
 
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\IntegrityConstraintViolationException;
 
 use Exception;
 
@@ -423,7 +424,7 @@ class Merge extends Query implements ConditionInterface {
           $insert->execute();
           return self::STATUS_INSERT;
         }
-        catch (Exception $e) {
+        catch (IntegrityConstraintViolationException $e) {
           // The insert query failed, maybe it's because a racing insert query
           // beat us in inserting the same row. Retry the select query, if it
           // returns a row, ignore the error and continue with the update
diff --git a/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php b/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php
index d877dba..b0ee0a3 100644
--- a/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php
+++ b/core/lib/Drupal/Core/Lock/DatabaseLockBackend.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Lock;
 
-use Drupal\Core\Database\DatabaseExceptionWrapper;
+use Drupal\Core\Database\IntegrityConstraintViolationException;
 
 /**
  * Defines the database lock backend. This is the default backend in Drupal.
@@ -53,12 +53,12 @@ class DatabaseLockBackend extends LockBackendAbstract {
           // We never need to try again.
           $retry = FALSE;
         }
-        catch (DatabaseExceptionWrapper $e) {
+        catch (IntegrityConstraintViolationException $e) {
           // Suppress the error. If this is our first pass through the loop,
-          // then $retry is FALSE. In this case, the insert must have failed
-          // meaning some other request acquired the lock but did not release it.
-          // We decide whether to retry by checking lock_may_be_available()
-          // Since this will break the lock in case it is expired.
+          // then $retry is FALSE. In this case, the insert failed because some
+          // other request acquired the lock but did not release it. We decide
+          // whether to retry by checking lockMayBeAvailable(). This will clear
+          // the offending row from the database table in case it has expired.
           $retry = $retry ? FALSE : $this->lockMayBeAvailable($name);
         }
         // We only retry in case the first attempt failed, but we then broke
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php
index e4b275e..b3599e4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php
@@ -37,7 +37,7 @@ abstract class CacheTestBase extends WebTestBase {
 
     $cached = cache($bin)->get($cid);
 
-    return isset($cached->data) && $cached->data == $var;
+    return $cached && $cached->data == $var;
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php
index 5cc023b..619f5a2 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -180,12 +180,14 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase {
     $backend = $this->getCacheBackend();
 
     $variables = array(
-      'test1' => 1,
-      'test2' => '0',
-      'test3' => '',
-      'test4' => 12.64,
-      'test5' => false,
-      'test6' => array(1,2,3),
+      'test1' => 0,
+      'test2' => 1,
+      'test3' => FALSE,
+      'test4' => NULL,
+      'test5' => '0',
+      'test6' => '',
+      'test7' => 12.64,
+      'test8' => array(1, 2, 3),
     );
 
     // Create cache entries.
@@ -400,8 +402,7 @@ abstract class GenericCacheBackendUnitTestBase extends UnitTestBase {
    *   TRUE on pass, FALSE on fail.
    */
   protected function checkCacheExists($cid, $bin = null) {
-    $cached = $this->getCacheBackend($bin)->get($cid);
-    return isset($cached->data);
+    return (bool) $this->getCacheBackend($bin)->get($cid);
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/InvalidDataTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/InvalidDataTest.php
index a2230be..906bfce 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/InvalidDataTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/InvalidDataTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Database;
 
+use Drupal\Core\Database\IntegrityConstraintViolationException;
 use Exception;
 
 /**
@@ -46,7 +47,7 @@ class InvalidDataTest extends DatabaseTestBase {
         ->execute();
       $this->fail(t('Insert succeedded when it should not have.'));
     }
-    catch (Exception $e) {
+    catch (IntegrityConstraintViolationException $e) {
       // Check if the first record was inserted.
       $name = db_query('SELECT name FROM {test} WHERE age = :age', array(':age' => 63))->fetchField();
 
