diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 454944c..505d1f1 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -428,6 +428,10 @@ protected function getFromStorage(array $ids = NULL) {
     $entities = array();
 
     if ($ids === NULL || $ids) {
+      if (!empty($ids)) {
+        $ids = $this->cleanIds($ids);
+      }
+
       // Build and execute the query.
       $query_result = $this->buildQuery($ids)->execute();
       $records = $query_result->fetchAllAssoc($this->idKey);
@@ -453,6 +457,30 @@ protected function getFromStorage(array $ids = NULL) {
   }
 
   /**
+   * Ensures integer entity IDs are valid.
+   *
+   * The identifier sanitization provided by this method has been introduced
+   * as Drupal used to rely on the database to facilitate this, which worked
+   * correctly with MySQL but led to errors with other DBMS such as PostgreSQL.
+   *
+   * @param array $ids
+   *   The entity IDs to verify.
+   * @return array
+   *   The sanitized list of entity IDs.
+   */
+  protected function cleanIds(array $ids) {
+    $definitions = $this->entityManager->getBaseFieldDefinitions($this->entityTypeId);
+    $id_definition = $definitions[$this->entityType->getKey('id')];
+    if ($id_definition->getType() == 'integer') {
+      $ids = array_filter($ids, function ($id) {
+        return is_numeric($id) && $id == (int) $id;
+      });
+      $ids = array_map('intval', $ids);
+    }
+    return $ids;
+  }
+
+  /**
    * Gets entities from the persistent cache backend.
    *
    * @param array|null &$ids
diff --git a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
index 656d8c9..1b4dc6b 100644
--- a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
@@ -70,6 +70,11 @@ function testEntityViewController() {
       $this->assertRaw($entity->label());
       $this->assertRaw('full');
     }
+
+    // As entity_test IDs must be integers, make sure requests for non-integer
+    // IDs return a page not found error.
+    $this->drupalGet('entity_test/invalid');
+    $this->assertResponse(404);
   }
 
   /**
diff --git a/core/modules/user/src/Tests/UserPasswordResetTest.php b/core/modules/user/src/Tests/UserPasswordResetTest.php
index 1d27865..e0ad691 100644
--- a/core/modules/user/src/Tests/UserPasswordResetTest.php
+++ b/core/modules/user/src/Tests/UserPasswordResetTest.php
@@ -38,21 +38,16 @@ protected function setUp() {
     $this->drupalPlaceBlock('system_menu_block:account');
 
     // Create a user.
-    $account = $this->drupalCreateUser();
+    $this->account = $this->drupalCreateUser();
 
     // Activate user by logging in.
-    $this->drupalLogin($account);
-
-    $this->account = user_load($account->id());
+    $this->drupalLogin($this->account);
     $this->drupalLogout();
 
     // Set the last login time that is used to generate the one-time link so
     // that it is definitely over a second ago.
-    $account->login = REQUEST_TIME - mt_rand(10, 100000);
-    db_update('users_field_data')
-      ->fields(array('login' => $account->getLastLoginTime()))
-      ->condition('uid', $account->id())
-      ->execute();
+    $this->account->setLastLoginTime(REQUEST_TIME - mt_rand(10, 100000));
+    $this->account->save();
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
index 420afba..d86fe33 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
@@ -1181,6 +1181,75 @@ public function testLoadMultiplePersistentCacheMiss() {
   }
 
   /**
+   * Tests entity ID sanitization.
+   */
+  public function testCleanIds() {
+    $valid_ids = array(
+      -1,
+      0,
+      1,
+      '-1',
+      '0',
+      '1',
+      0123,
+      -0x1A,
+      0x1AFC,
+      -0b111,
+      0b101,
+      '0123',
+      '00123',
+      '000123',
+      '-0123',
+      '-00123',
+      '-000123',
+      -10.0,
+      -1.0,
+      0.0,
+      1.0,
+      10.0,
+      -10.00,
+      -1.00,
+      0.00,
+      1.00,
+      10.00,
+    );
+
+    $this->fieldDefinitions = $this->mockFieldDefinitions(array('id'));
+    $this->fieldDefinitions['id']->expects($this->any())
+    ->method('getType')
+    ->will($this->returnValue('integer'));
+
+    $this->setUpEntityStorage();
+
+    $this->entityType->expects($this->any())
+    ->method('getKey')
+    ->will($this->returnValueMap(array(
+      array('id', 'id'),
+    )));
+
+    $method = new \ReflectionMethod($this->entityStorage, 'cleanIds');
+    $method->setAccessible(TRUE);
+    $this->assertEquals($valid_ids, $method->invoke($this->entityStorage, $valid_ids));
+
+    $invalid_ids = array(
+      '--1',
+      '-0x1A',
+      '0x1AFC',
+      '-0b111',
+      '0b101',
+      'a',
+      FALSE,
+      TRUE,
+      NULL,
+      '32acb',
+      123.123,
+      123.678,
+    );
+    $this->assertEquals(array(), $method->invoke($this->entityStorage, $invalid_ids));
+
+  }
+
+  /**
    * Sets up the module handler with no implementations.
    */
   protected function setUpModuleHandlerNoImplementations() {
