diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 755c2c1..475d8d1 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -342,17 +342,8 @@ function install_begin_request(&$install_state) {
   module_list(NULL, $module_list);
   drupal_load('module', 'system');
 
-  // Load the cache infrastructure using a "fake" cache implementation that
-  // does not attempt to write to the database. We need this during the initial
-  // part of the installer because the database is not available yet. We
-  // continue to use it even when the database does become available, in order
-  // to preserve consistency between interactive and command-line installations
-  // (the latter complete in one page request and therefore are forced to
-  // continue using the cache implementation they started with) and also
-  // because any data put in the cache during the installer is inherently
-  // suspect, due to the fact that Drupal is not fully set up yet.
   require_once DRUPAL_ROOT . '/core/includes/cache.inc';
-  $conf['cache_classes'] = array('cache' => 'Drupal\Core\Cache\InstallBackend');
+  $conf['cache_classes'] = array('cache' => 'Drupal\Core\Cache\NullBackend');
 
   // The install process cannot use the database lock backend since the database
   // is not fully up, so we use a null backend implementation during the
@@ -1496,6 +1487,8 @@ function install_load_profile(&$install_state) {
  *   An array of information about the current installation state.
  */
 function install_bootstrap_full(&$install_state) {
+  unset($GLOBALS['conf']['cache_classes']['cache']);
+  drupal_static_reset('cache');
   // Clear the module list that was overriden earlier in the process.
   // This will allow all freshly installed modules to be loaded.
   module_list_reset();
diff --git a/core/includes/update.inc b/core/includes/update.inc
index b8e8ee6..3bb4e7b 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -136,7 +136,10 @@ function update_prepare_d8_bootstrap() {
   }
 
   // Bootstrap the database.
+  $GLOBALS['conf']['cache_classes'] = array('cache' => 'Drupal\Core\Cache\NullBackend');
   drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
+  unset($GLOBALS['conf']['cache_classes']['cache']);
+  drupal_static_reset('cache');
 
   // If the site has not updated to Drupal 8 yet, check to make sure that it is
   // running an up-to-date version of Drupal 7 before proceeding. Note this has
@@ -195,6 +198,116 @@ function update_prepare_d8_bootstrap() {
         );
         db_create_table('key_value', $specs);
       }
+      if (!db_table_exists('cache_tags')) {
+        $table = array(
+          'description' => 'Cache table for tracking cache tags related to the cache bin.',
+          'fields' => array(
+            'tag' => array(
+              'description' => 'Namespace-prefixed tag string.',
+              'type' => 'varchar',
+              'length' => 255,
+              'not null' => TRUE,
+              'default' => '',
+            ),
+            'invalidations' => array(
+              'description' => 'Number incremented when the tag is invalidated.',
+              'type' => 'int',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+            'deletions' => array(
+              'description' => 'Number incremented when the tag is deleted.',
+              'type' => 'int',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+          ),
+          'primary key' => array('tag'),
+        );
+        db_create_table('cache_tags', $table);
+      }
+      if (!db_table_exists('cache_config')) {
+        $spec = array(
+          'description' =>  'Cache table for configuration data.',
+          'fields' => array(
+            'cid' => array(
+              'description' => 'Primary Key: Unique cache ID.',
+              'type' => 'varchar',
+              'length' => 255,
+              'not null' => TRUE,
+              'default' => '',
+            ),
+            'data' => array(
+              'description' => 'A collection of data to cache.',
+              'type' => 'blob',
+              'not null' => FALSE,
+              'size' => 'big',
+            ),
+            'expire' => array(
+              'description' => 'A Unix timestamp indicating when the cache entry should expire, or 0 for never.',
+              'type' => 'int',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+            'created' => array(
+              'description' => 'A Unix timestamp indicating when the cache entry was created.',
+              'type' => 'int',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+            'serialized' => array(
+              'description' => 'A flag to indicate whether content is serialized (1) or not (0).',
+              'type' => 'int',
+              'size' => 'small',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+            'tags' => array(
+              'description' => 'Space-separated list of cache tags for this entry.',
+              'type' => 'text',
+              'size' => 'big',
+              'not null' => FALSE,
+            ),
+            'checksum_invalidations' => array(
+              'description' => 'The tag invalidation sum when this entry was saved.',
+              'type' => 'int',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+            'checksum_deletions' => array(
+              'description' => 'The tag deletion sum when this entry was saved.',
+              'type' => 'int',
+              'not null' => TRUE,
+              'default' => 0,
+            ),
+          ),
+          'indexes' => array(
+            'expire' => array('expire'),
+          ),
+          'primary key' => array('cid'),
+        );
+        db_create_table('cache_config', $spec);
+      }
+
+      require_once DRUPAL_ROOT . '/core/modules/system/system.install';
+      $tables = array(
+        'cache',
+        'cache_bootstrap',
+        'cache_block',
+        'cache_field',
+        'cache_filter',
+        'cache_form',
+        'cache_image',
+        'cache_menu',
+        'cache_page',
+        'cache_path',
+        'cache_update',
+      );
+
+      foreach ($tables as $table) {
+        update_add_cache_columns($table);
+      }
+
       // Bootstrap variables so we can update theme while preparing the update
       // process.
       drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
@@ -1333,3 +1446,33 @@ function update_add_uuids(&$sandbox, $table, $primary_key, $values) {
     $sandbox['last'] = $value;
   }
 }
+
+
+/**
+ * Adds tags, checksum_invalidations, checksum_deletions to a cache table.
+ *
+ * @param string $table
+ *   Name of the cache table.
+ */
+function update_add_cache_columns($table) {
+  if (db_table_exists($table) && !db_field_exists($table, 'tags')) {
+    db_add_field($table, 'tags', array(
+      'description' => 'Space-separated list of cache tags for this entry.',
+      'type' => 'text',
+      'size' => 'big',
+      'not null' => FALSE,
+    ));
+    db_add_field($table, 'checksum_invalidations', array(
+      'description' => 'The tag invalidation sum when this entry was saved.',
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ));
+    db_add_field($table, 'checksum_deletions', array(
+      'description' => 'The tag deletion sum when this entry was saved.',
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ));
+  }
+}
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 8a73a20..dc77e3e 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Cache;
 
 use Drupal\Core\Database\Database;
+use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Exception;
 use PDO;
 
@@ -52,30 +53,23 @@ public function get($cid, $allow_invalid = FALSE) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
   public function getMultiple(&$cids, $allow_invalid = FALSE) {
-    try {
-      // When serving cached pages, the overhead of using ::select() was found
-      // to add around 30% overhead to the request. Since $this->bin is a
-      // variable, this means the call to ::query() here uses a concatenated
-      // string. This is highly discouraged under any other circumstances, and
-      // is used here only due to the performance overhead we would incur
-      // otherwise. When serving an uncached page, the overhead of using
-      // ::select() is a much smaller proportion of the request.
-      $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
-      $cache = array();
-      foreach ($result as $item) {
-        $item = $this->prepareItem($item, $allow_invalid);
-        if ($item) {
-          $cache[$item->cid] = $item;
-        }
+    // When serving cached pages, the overhead of using ::select() was found
+    // to add around 30% overhead to the request. Since $this->bin is a
+    // variable, this means the call to ::query() here uses a concatenated
+    // string. This is highly discouraged under any other circumstances, and
+    // is used here only due to the performance overhead we would incur
+    // otherwise. When serving an uncached page, the overhead of using
+    // ::select() is a much smaller proportion of the request.
+    $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
+    $cache = array();
+    foreach ($result as $item) {
+      $item = $this->prepareItem($item, $allow_invalid);
+      if ($item) {
+        $cache[$item->cid] = $item;
       }
-      $cids = array_diff($cids, array_keys($cache));
-      return $cache;
-    }
-    catch (Exception $e) {
-      // If the database is never going to be available, cache requests should
-      // return FALSE in order to allow exception handling to occur.
-      return array();
     }
+    $cids = array_diff($cids, array_keys($cache));
+    return $cache;
   }
 
   /**
@@ -131,33 +125,36 @@ protected function prepareItem($cache, $allow_invalid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
-    try {
-      $flat_tags = $this->flattenTags($tags);
-      $checksum = $this->checksumTags($flat_tags);
-      $fields = array(
-        'serialized' => 0,
-        'created' => REQUEST_TIME,
-        'expire' => $expire,
-        'tags' => implode(' ', $flat_tags),
-        'checksum_invalidations' => $checksum['invalidations'],
-        'checksum_deletions' => $checksum['deletions'],
-      );
-      if (!is_string($data)) {
-        $fields['data'] = serialize($data);
-        $fields['serialized'] = 1;
-      }
-      else {
-        $fields['data'] = $data;
-        $fields['serialized'] = 0;
-      }
+    $flat_tags = $this->flattenTags($tags);
+    $checksum = $this->checksumTags($flat_tags);
+    $fields = array(
+      'serialized' => 0,
+      'created' => REQUEST_TIME,
+      'expire' => $expire,
+      'tags' => implode(' ', $flat_tags),
+      'checksum_invalidations' => $checksum['invalidations'],
+      'checksum_deletions' => $checksum['deletions'],
+    );
+    if (!is_string($data)) {
+      $fields['data'] = serialize($data);
+      $fields['serialized'] = 1;
+    }
+    else {
+      $fields['data'] = $data;
+      $fields['serialized'] = 0;
+    }
 
+    try {
       Database::getConnection()->merge($this->bin)
         ->key(array('cid' => $cid))
         ->fields($fields)
         ->execute();
     }
-    catch (Exception $e) {
-      // The database may not be available, so we'll ignore cache_set requests.
+    catch (DatabaseExceptionWrapper $e) {
+      // If set() failed for whatever reason, then try to delete() to avoid a
+      // stale cache. Removing this causes sporadic testbot failures due to
+      // what seems a bug in the InnoDB deadlock detection heuristics.
+      $this->delete($cid);
     }
   }
 
diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php
deleted file mode 100644
index 91d0249..0000000
--- a/core/lib/Drupal/Core/Cache/InstallBackend.php
+++ /dev/null
@@ -1,187 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\Cache\InstallBackend.
- */
-
-namespace Drupal\Core\Cache;
-
-use Exception;
-
-/**
- * Defines a stub cache implementation to be used during installation.
- *
- * The stub implementation is needed when database access is not yet available.
- * Because Drupal's caching system never requires that cached data be present,
- * these stub functions can short-circuit the process and sidestep the need for
- * any persistent storage. Obviously, using this cache implementation during
- * normal operations would have a negative impact on performance.
- *
- * If there is a database cache, this backend will attempt to clear it whenever
- * possible. The reason for doing this is that the database cache can accumulate
- * data during installation due to any full bootstraps that may occur at the
- * same time (for example, Ajax requests triggered by the installer). If we
- * didn't try to clear it whenever one of the delete function are called, the
- * data in the cache would become stale; for example, the installer sometimes
- * calls variable_set(), which updates the {variable} table and then clears the
- * cache to make sure that the next page request picks up the new value.
- * Not actually clearing the cache here therefore leads old variables to be
- * loaded on the first page requests after installation, which can cause
- * subtle bugs, some of which would not be fixed unless the site
- * administrator cleared the cache manually.
- */
-class InstallBackend extends DatabaseBackend {
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::get().
-   */
-  public function get($cid, $allow_invalid = FALSE) {
-    return FALSE;
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::getMultiple().
-   */
-  public function getMultiple(&$cids, $allow_invalid = FALSE) {
-    return array();
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::set().
-   */
-  public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {}
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::delete().
-   */
-  public function delete($cid) {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::delete($cid);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteMultiple().
-   */
-  public function deleteMultiple(array $cids) {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::deleteMultiple($cids);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteAll().
-   */
-  public function deleteAll() {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::deleteAll();
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteExpired().
-   */
-  public function deleteExpired() {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::deleteExpired();
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteTags().
-   */
-  public function deleteTags(array $tags) {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::deleteTags($tags);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidate().
-   */
-  public function invalidate($cid) {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::invalidate($cid);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateMultiple().
-   */
-  public function invalidateMultiple(array $cids) {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::invalidateMultiple($cids);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::invalidateTags($tags);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
-   */
-  public function invalidateAll() {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::invalidateAll($tags);
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::garbageCollection().
-   */
-  public function garbageCollection() {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        parent::garbageCollection();
-      }
-    }
-    catch (Exception $e) {}
-  }
-
-  /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::isEmpty().
-   */
-  public function isEmpty() {
-    try {
-      if (class_exists('Drupal\Core\Database\Database')) {
-        return parent::isEmpty();
-      }
-    }
-    catch (Exception $e) {}
-    return TRUE;
-  }
-}
diff --git a/core/lib/Drupal/Core/Database/Query/Merge.php b/core/lib/Drupal/Core/Database/Query/Merge.php
index ee0406a..b2db00f 100644
--- a/core/lib/Drupal/Core/Database/Query/Merge.php
+++ b/core/lib/Drupal/Core/Database/Query/Merge.php
@@ -124,6 +124,13 @@ class Merge extends Query implements ConditionInterface {
   protected $needsUpdate = FALSE;
 
   /**
+   * TRUE when execute() runs for the second time.
+   *
+   * @var boolean
+   */
+  protected $retry = FALSE;
+
+  /**
   * Constructs a Merge object.
   *
   * @param Drupal\Core\Database\Connection $connection
@@ -416,16 +423,16 @@ public function execute() {
           $insert->useDefaults($this->defaultFields);
         }
         $insert->execute();
+        $this->retry = FALSE;
         return self::STATUS_INSERT;
       }
       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
-        // query below.
-        if (!$select->execute()->fetchField()) {
+        // Retry only once.
+        if ($this->retry) {
           throw $e;
         }
+        $this->retry = TRUE;
+        return $this->execute();
       }
     }
     if ($this->needsUpdate) {
@@ -438,6 +445,7 @@ public function execute() {
         }
       }
       $update->execute();
+      $this->retry = FALSE;
       return self::STATUS_UPDATE;
     }
   }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
deleted file mode 100644
index 65cb303..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Cache\InstallTest.
- */
-
-namespace Drupal\system\Tests\Cache;
-
-use Drupal\Core\Cache\DatabaseBackend;
-use Drupal\Core\Cache\InstallBackend;
-use Exception;
-
-/**
- * Tests the behavior of the cache backend used for installing Drupal.
- */
-class InstallTest extends CacheTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('cache_test');
-
-  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',
-    );
-  }
-
-  /**
-   * Tests the behavior of the cache backend used for installing Drupal.
-   *
-   * While Drupal is being installed, the cache system must 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 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 cache (Drupal\Core\Cache\InstallBackend) while setting and
-   * clearing various items in the cache.
-   */
-  function testCacheInstall() {
-    $database_cache = new DatabaseBackend('test');
-    $install_cache = new InstallBackend('test');
-
-    // Store an item in the database cache, and confirm that the installer's
-    // cache backend recognizes that the cache is not empty.
-    $database_cache->set('cache_one', 'One');
-    $this->assertFalse($install_cache->isEmpty());
-    $database_cache->delete('cache_one');
-    $this->assertTrue($install_cache->isEmpty());
-
-    // 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.
-    $database_cache->set('cache_one', 'One');
-    $this->assertEqual($database_cache->get('cache_one')->data, 'One');
-    $install_cache->delete('cache_one');
-    $this->assertFalse($database_cache->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.
-    $database_cache->set('cache_one', 'One');
-    $database_cache->set('cache_two', 'Two');
-    $this->assertEqual($database_cache->get('cache_one')->data, 'One');
-    $this->assertEqual($database_cache->get('cache_two')->data, 'Two');
-    $install_cache->deleteMultiple(array('cache_one', 'cache_two'));
-    $this->assertFalse($database_cache->get('cache_one'));
-    $this->assertFalse($database_cache->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.
-    $database_cache->set('cache_one', 'One');
-    $database_cache->set('cache_two', 'Two');
-    $this->assertEqual($database_cache->get('cache_one')->data, 'One');
-    $this->assertEqual($database_cache->get('cache_two')->data, 'Two');
-    $install_cache->deleteAll();
-    $this->assertFalse($database_cache->get('cache_one'));
-    $this->assertFalse($database_cache->get('cache_two'));
-
-    // Invalidate a tag using the installer cache, then check that the
-    // invalidation was recorded correctly in the database.
-    $install_cache->invalidateTags(array('tag'));
-    $invalidations = db_query("SELECT invalidations FROM {cache_tags} WHERE tag = 'tag'")->fetchField();
-    $this->assertEqual($invalidations, 1);
-
-    // 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');
-    try {
-      $install_cache->isEmpty();
-      $install_cache->delete('cache_one');
-      $install_cache->deleteMultiple(array('cache_one', 'cache_two'));
-      $install_cache->deleteAll();
-      $install_cache->deleteExpired();
-      $install_cache->garbageCollection();
-      $install_cache->invalidateTags(array('tag'));
-      $this->pass("The installer's cache backend can be used even when the cache database tables are unavailable.");
-    }
-    catch (Exception $e) {
-      $this->fail("The installer's cache backend can be used even when the cache database tables are unavailable.");
-    }
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
index cc60abd..37d893d 100644
--- a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
@@ -38,6 +38,7 @@ function testCompileDIC() {
       'directory' => DRUPAL_ROOT . '/' . variable_get('file_public_path', conf_path() . '/files') . '/php',
       'secret' => $GLOBALS['drupal_hash_salt'],
     );
+    $conf['cache_classes'] = array('cache' => 'Drupal\Core\Cache\NullBackend');
     // @todo: write a memory based storage backend for testing.
     $module_enabled = array(
       'system' => 'system',
@@ -105,5 +106,6 @@ function testCompileDIC() {
     // Check that the location of the new module is registered.
     $modules = $container->getParameter('container.modules');
     $this->assertEqual($modules['bundle_test'], drupal_get_filename('module', 'bundle_test'));
+    unset($conf['cache_classes']);
   }
 }
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 8c7d72a..71e21c3 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1519,66 +1519,7 @@ function system_update_8002() {
  * Creates {cache_config} cache table for the new configuration system.
  */
 function system_update_8003() {
-  $spec = array(
-    'description' =>  'Cache table for configuration data.',
-    'fields' => array(
-      'cid' => array(
-        'description' => 'Primary Key: Unique cache ID.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'data' => array(
-        'description' => 'A collection of data to cache.',
-        'type' => 'blob',
-        'not null' => FALSE,
-        'size' => 'big',
-      ),
-      'expire' => array(
-        'description' => 'A Unix timestamp indicating when the cache entry should expire, or 0 for never.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'created' => array(
-        'description' => 'A Unix timestamp indicating when the cache entry was created.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'serialized' => array(
-        'description' => 'A flag to indicate whether content is serialized (1) or not (0).',
-        'type' => 'int',
-        'size' => 'small',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'tags' => array(
-        'description' => 'Space-separated list of cache tags for this entry.',
-        'type' => 'text',
-        'size' => 'big',
-        'not null' => FALSE,
-      ),
-      'checksum_invalidations' => array(
-        'description' => 'The tag invalidation sum when this entry was saved.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'checksum_deletions' => array(
-        'description' => 'The tag deletion sum when this entry was saved.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-    ),
-    'indexes' => array(
-      'expire' => array('expire'),
-    ),
-    'primary key' => array('cid'),
-  );
-  db_create_table('cache_config', $spec);
+  // Moved to update_prepare_d8_bootstrap.
 }
 
 /**
@@ -1626,84 +1567,14 @@ function system_update_8005() {
  * Adds the {cache_tags} table.
  */
 function system_update_8006() {
-  $table = array(
-    'description' => 'Cache table for tracking cache tags related to the cache bin.',
-    'fields' => array(
-      'tag' => array(
-        'description' => 'Namespace-prefixed tag string.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'invalidations' => array(
-        'description' => 'Number incremented when the tag is invalidated.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'deletions' => array(
-        'description' => 'Number incremented when the tag is deleted.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-    ),
-    'primary key' => array('tag'),
-  );
-  db_create_table('cache_tags', $table);
-}
-
-/**
- * Adds tags, checksum_invalidations, checksum_deletions to a cache table.
- *
- * @param string $table
- *   Name of the cache table.
- */
-function system_update_8007_add_tag_column($table) {
-  if (db_table_exists($table)) {
-    db_add_field($table, 'tags', array(
-      'description' => 'Space-separated list of cache tags for this entry.',
-      'type' => 'text',
-      'size' => 'big',
-      'not null' => FALSE,
-    ));
-    db_add_field($table, 'checksum_invalidations', array(
-      'description' => 'The tag invalidation sum when this entry was saved.',
-      'type' => 'int',
-      'not null' => TRUE,
-      'default' => 0,
-    ));
-    db_add_field($table, 'checksum_deletions', array(
-      'description' => 'The tag deletion sum when this entry was saved.',
-      'type' => 'int',
-      'not null' => TRUE,
-      'default' => 0,
-    ));
-  }
+  // Moved to update_prepare_d8_bootstrap.
 }
 
 /**
  * Modifies existing cache tables, adding support for cache tags.
  */
 function system_update_8007() {
-  $tables = array(
-    'cache',
-    'cache_bootstrap',
-    'cache_form',
-    'cache_page',
-    'cache_menu',
-    'cache_path',
-    'cache_filter',
-    'cache_image',
-    'cache_update',
-    'cache_block',
-    'cache_field',
-  );
-
-  foreach ($tables as $table) {
-    system_update_8007_add_tag_column($table);
-  }
+  // Moved to update_prepare_d8_bootstrap.
 }
 
 /**
diff --git a/core/modules/views/lib/Drupal/views/ViewsDataCache.php b/core/modules/views/lib/Drupal/views/ViewsDataCache.php
index 4df7ff5..b117d52 100644
--- a/core/modules/views/lib/Drupal/views/ViewsDataCache.php
+++ b/core/modules/views/lib/Drupal/views/ViewsDataCache.php
@@ -205,14 +205,19 @@ protected function processEntityTypes(array &$data) {
    * Destructs the ViewDataCache object.
    */
   public function __destruct() {
-    if ($this->rebuildCache && !empty($this->storage)) {
-      // Keep a record with all data.
-      $this->set($this->baseCid, $this->storage);
-      // Save data in seperate cache entries.
-      foreach ($this->storage as $table => $data) {
-        $cid = $this->baseCid . ':' . $table;
-        $this->set($cid, $data);
+    try {
+      if ($this->rebuildCache && !empty($this->storage)) {
+        // Keep a record with all data.
+        $this->set($this->baseCid, $this->storage);
+        // Save data in seperate cache entries.
+        foreach ($this->storage as $table => $data) {
+          $cid = $this->baseCid . ':' . $table;
+          $this->set($cid, $data);
+        }
       }
+    } catch (\Exception $e) {
+      // During testing the table is gone before this fires. Nasty.
+      // @todo remove after http://drupal.org/node/512026.
     }
   }
 
