diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php
index f332fcc..1739ada 100644
--- a/core/lib/Drupal/Core/Cache/InstallBackend.php
+++ b/core/lib/Drupal/Core/Cache/InstallBackend.php
@@ -53,7 +53,7 @@ class InstallBackend extends DatabaseBackend {
   function set($cid, $data, $expire = CACHE_PERMANENT, array $tags = array()) {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::delete().
+   * Overrides Drupal\Core\Cache\CacheBackendInterface::delete().
    */
   function delete($cid) {
     try {
@@ -65,7 +65,7 @@ class InstallBackend extends DatabaseBackend {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
+   * Overrides Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
    */
   function deleteMultiple(array $cids) {
     try {
@@ -77,7 +77,7 @@ class InstallBackend extends DatabaseBackend {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix().
+   * Overrides Drupal\Core\Cache\CacheBackendInterface::deletePrefix().
    */
   function deletePrefix($prefix) {
     try {
@@ -98,7 +98,7 @@ class InstallBackend extends DatabaseBackend {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::flush().
+   * Overrides Drupal\Core\Cache\CacheBackendInterface::flush().
    */
   function flush() {
     try {
@@ -110,9 +110,39 @@ class InstallBackend extends DatabaseBackend {
   }
 
   /**
+   * Overrides Drupal\Core\Cache\CacheBackendInterface::expire().
+   */
+  function expire() {
+    try {
+      if (class_exists('Database')) {
+        parent::expire();
+      }
+    }
+    catch (Exception $e) {}
+  }
+
+  /**
+   * Overrides Drupal\Core\Cache\CacheBackendInterface::garbageCollection().
+   */
+  function garbageCollection() {
+    try {
+      if (class_exists('Database')) {
+        parent::garbageCollection();
+      }
+    }
+    catch (Exception $e) {}
+  }
+
+  /**
    * Overrides Drupal\Core\Cache\CacheBackendInterface::isEmpty().
    */
   function isEmpty() {
+    try {
+      if (class_exists('Database')) {
+        return parent::isEmpty();
+      }
+    }
+    catch (Exception $e) {}
     return TRUE;
   }
 }
diff --git a/core/modules/system/tests/cache.test b/core/modules/system/tests/cache.test
index e5d4435..d76acf4 100644
--- a/core/modules/system/tests/cache.test
+++ b/core/modules/system/tests/cache.test
@@ -454,3 +454,162 @@ class CacheIsEmptyCase extends CacheTestCase {
     $this->assertTrue($cache->isEmpty(), t('The cache bin is empty'));
   }
 }
+
+/**
+ * Tests the behavior of the cache backend used for installing Drupal.
+ */
+class CacheInstallTestCase extends DrupalWebTestCase {
+  protected $profile = 'testing';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Cache install test',
+      'description' => 'Confirm that the cache backend used for installing Drupal works correctly.',
+      'group' => 'Cache',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('cache_test'));
+  }
+
+  /**
+   * Tests the behavior of the cache backend used for installing Drupal.
+   *
+   * While Drupal is being installed, the cache system must properly deal with
+   * the fact that the database is not initially available, and, after it is
+   * available, the fact that other requests that take place while Drupal is
+   * being installed (for example, Ajax requests triggered via the installer's
+   * user interface) may cache data in the database, which needs to be properly
+   * cleared when the installer makes changes that would result in it becoming
+   * stale.
+   *
+   * We cannot test this process directly, so instead we test it by switching
+   * between the normal database cache (Drupal\Core\Cache\DatabaseBackend) and
+   * the installer database cache (Drupal\Core\Cache\InstallBackend) while
+   * setting and clearing various items in the cache. Since Drupal does not
+   * allow the cache backend to change within a single page request, we use the
+   * 'cache_test' module as a helper to perform each cache operation in a
+   * separate page request. This also more closely simulates what happens
+   * during the installer (where Ajax requests that populate the cache are
+   * separate from installer requests that may need to clear it).
+   */
+  function testCacheInstall() {
+    // Store an item in the database cache, then use the installer's cache
+    // backend to delete it. Afterwards, confirm that it is no longer in the
+    // database cache.
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_one'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+
+    // Store an item in the cache, then use the installer's cache backend to
+    // check if the cache is populated and, if so, delete it. Aftewards,
+    // confirm it is no longer in the database cache.
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_one'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete_if_not_empty'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+
+    // Store multiple items in the database cache, then use the installer's
+    // cache backend to delete them. Afterwards, confirm that they are no
+    // longer in the database cache.
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_multiple'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    $this->assertEqual(cache('test')->get('cache_two')->data, 'Two');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete_multiple'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+    $this->assertFalse(cache('test')->get('cache_two'));
+
+    // Store multiple items in the database cache, then use the installer's
+    // cache backend to delete them via a wildcard prefix. Afterwards, confirm
+    // that they are no longer in the database cache.
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_multiple'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    $this->assertEqual(cache('test')->get('cache_two')->data, 'Two');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete_prefix'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+    $this->assertFalse(cache('test')->get('cache_two'));
+
+    // Store multiple items in the database cache, then use the installer's
+    // cache backend to flush the cache. Afterwards, confirm that they are no
+    // longer in the database cache.
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_multiple'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    $this->assertEqual(cache('test')->get('cache_two')->data, 'Two');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_flush'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+    $this->assertFalse(cache('test')->get('cache_two'));
+
+    // Store multiple items in the database cache with a temporary expiration,
+    // then use the installer's cache backend to expire outdated items.
+    // Afterwards, confirm that they are no longer in the database cache.
+    variable_set('cache_lifetime', 0);
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_multiple_temporary'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    $this->assertEqual(cache('test')->get('cache_two')->data, 'Two');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_expire'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+    $this->assertFalse(cache('test')->get('cache_two'));
+
+    // Store multiple items in the database cache with a temporary expiration,
+    // then use the installer's cache backend to perform garbage collection.
+    // Afterwards, confirm that they are no longer in the database cache.
+    variable_set('cache_lifetime', 0);
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_set_multiple_temporary'), 'Save');
+    $this->assertEqual(cache('test')->get('cache_one')->data, 'One');
+    $this->assertEqual(cache('test')->get('cache_two')->data, 'Two');
+    // After we've checked that the items are in the cache, we need to enable
+    // garbage collection before running the garbage collector.
+    variable_set('cache_flush_cache_test', 1);
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_garbage_collection'), 'Save');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\DatabaseBackend');
+    $this->assertFalse(cache('test')->get('cache_one'));
+    $this->assertFalse(cache('test')->get('cache_two'));
+
+    // For each cache clearing event that we tried above, try it again after
+    // dropping the {cache_test} table. This simulates the early stages of the
+    // installer (when the database cache tables won't be available yet) and
+    // thereby confirms that the installer's cache backend does not produce
+    // errors if the installer ever calls any code early on that tries to clear
+    // items from the cache.
+    db_drop_table('cache_test');
+    variable_set('cache_class_test', 'Drupal\Core\Cache\InstallBackend');
+    variable_set('cache_lifetime', 0);
+    variable_set('cache_flush_cache_test', 1);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete'), 'Save');
+    $this->assertResponse(200);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete_if_not_empty'), 'Save');
+    $this->assertResponse(200);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete_multiple'), 'Save');
+    $this->assertResponse(200);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_delete_prefix'), 'Save');
+    $this->assertResponse(200);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_flush'), 'Save');
+    $this->assertResponse(200);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_expire'), 'Save');
+    $this->assertResponse(200);
+    $this->drupalPost('cache-install-test', array('test_to_perform' => 'cache_test_garbage_collection'), 'Save');
+    $this->assertResponse(200);
+  }
+}
diff --git a/core/modules/system/tests/cache_test/cache_test.info b/core/modules/system/tests/cache_test/cache_test.info
new file mode 100644
index 0000000..095b6fd
--- /dev/null
+++ b/core/modules/system/tests/cache_test/cache_test.info
@@ -0,0 +1,6 @@
+name = "Cache test"
+description = "Support module for cache system testing."
+package = Testing
+version = VERSION
+core = 8.x
+hidden = TRUE
diff --git a/core/modules/system/tests/cache_test/cache_test.install b/core/modules/system/tests/cache_test/cache_test.install
new file mode 100644
index 0000000..5b50e11
--- /dev/null
+++ b/core/modules/system/tests/cache_test/cache_test.install
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the cache_test module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function cache_test_schema() {
+  $schema['cache_test'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_test']['description'] = 'Cache table for testing the cache system.';
+  return $schema;
+}
diff --git a/core/modules/system/tests/cache_test/cache_test.module b/core/modules/system/tests/cache_test/cache_test.module
new file mode 100644
index 0000000..0c76587
--- /dev/null
+++ b/core/modules/system/tests/cache_test/cache_test.module
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * @file
+ * Support module for testing the cache system.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function cache_test_menu() {
+  $items['cache-install-test'] = array(
+    'title' => 'Cache install testing',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('cache_test_install_form'),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+  return $items;
+}
+
+/**
+ * Form constructor for the cache install testing form.
+ *
+ * @see cache_test_install_form_submit()
+ * @ingroup forms
+ */
+function cache_test_install_form($form, &$form_state) {
+  $form['test_to_perform'] = array(
+    '#type' => 'radios',
+    '#title' => 'Test to perform',
+    '#options' => array(
+      'cache_test_set_one' => 'Store one item in the cache.',
+      'cache_test_set_multiple' => 'Store multiple items in the cache.',
+      'cache_test_set_multiple_temporary' => 'Store multiple items in the cache for a temporary period of time.',
+      'cache_test_delete' => 'Delete one item from the cache, using delete().',
+      'cache_test_delete_if_not_empty' => 'Delete one item from the cache only if the cache is not empty.',
+      'cache_test_delete_multiple' => 'Delete multiple items from the cache, using deleteMultiple().',
+      'cache_test_delete_prefix' => 'Delete items from the cache with a wildcard prefix, using deletePrefix().',
+      'cache_test_flush' => 'Flush all items from the cache.',
+      'cache_test_expire' => 'Expire outdated items from the cache.',
+      'cache_test_garbage_collection' => 'Perform garbage collection on the cache.',
+    ),
+    '#required' => TRUE,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Save',
+  );
+
+  return $form;
+}
+
+/**
+ * Form submission handler cache_test_install_form().
+ */
+function cache_test_install_form_submit($form, &$form_state) {
+  // Call the function corresponding to the test that was requested.
+  $form_state['values']['test_to_perform']();
+}
+
+/**
+ * Stores one item in the cache.
+ */
+function cache_test_set_one() {
+  cache('test')->set('cache_one', 'One');
+}
+
+/**
+ * Stores multiple items in the cache.
+ */
+function cache_test_set_multiple() {
+  $cache = cache('test');
+  $cache->set('cache_one', 'One');
+  $cache->set('cache_two', 'Two');
+}
+
+/**
+ * Stores multiple items in the cache for a temporary period of time.
+ */
+function cache_test_set_multiple_temporary() {
+  $cache = cache('test');
+  $cache->set('cache_one', 'One', CACHE_TEMPORARY);
+  $cache->set('cache_two', 'Two', CACHE_TEMPORARY);
+}
+
+/**
+ * Deletes one item from the cache, using delete().
+ */
+function cache_test_delete() {
+  cache('test')->delete('cache_one');
+}
+
+/**
+ * Deletes one item from the cache only if the cache is not empty.
+ */
+function cache_test_delete_if_not_empty() {
+  $cache = cache('test');
+  if (!$cache->isEmpty()) {
+    $cache->delete('cache_one');
+  }
+}
+
+/**
+ * Deletes multiple items from the cache, using deleteMultiple().
+ */
+function cache_test_delete_multiple() {
+  cache('test')->deleteMultiple(array('cache_one', 'cache_two'));
+}
+
+/**
+ * Deletes items from the cache with a wildcard prefix, using deletePrefix().
+ */
+function cache_test_delete_prefix() {
+  cache('test')->deletePrefix('cache_');
+}
+
+/**
+ * Flushes all items from the cache.
+ */
+function cache_test_flush() {
+  cache('test')->flush();
+}
+
+/**
+ * Expires outdated items from the cache.
+ */
+function cache_test_expire() {
+  cache('test')->expire();
+}
+
+/**
+ * Performs garbage collection on the cache.
+ */
+function cache_test_garbage_collection() {
+  cache('test')->garbageCollection();
+}
