diff --git a/core/includes/module.inc b/core/includes/module.inc
index 11f8244..85c0240 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -5,9 +5,11 @@
  * API for loading and interacting with Drupal modules.
  */
 
-use Drupal\Component\Graph\Graph;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Yaml\Parser;
 
 /**
  * Builds a list of bootstrap modules and enabled modules and themes.
@@ -566,7 +568,6 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE)
     $module_list = array_keys($module_list);
   }
 
-  $storage = drupal_container()->get('config.storage');
   $schema_store = Drupal::keyValue('system.schema');
   $disabled_config = config('system.module.disabled');
   foreach ($module_list as $module) {
@@ -578,6 +579,38 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE)
     // Remove all configuration belonging to the module.
     config_uninstall_default_config('module', $module);
 
+    // Remove any cache bins defined by the module.
+    $service_yaml_file = drupal_get_path('module', $module) . "/$module.services.yml";
+    if (file_exists($service_yaml_file)) {
+      $parser = new Parser;
+      $definitions = $parser->parse(file_get_contents($service_yaml_file));
+      if (isset($definitions['services'])) {
+        foreach ($definitions['services'] as $id => $definition) {
+          if (isset($definition['tags'])) {
+            foreach ($definition['tags'] as $tag) {
+              // This works for the default cache registration and even in some
+              // cases when a non-default "super" factory is used. That should
+              // be extremely rare.
+              if ($tag['name'] == 'cache.bin' && isset($definition['factory_service']) && isset($definition['factory_method']) && !empty($definition['arguments'])) {
+                try {
+                  $factory = Drupal::service($definition['factory_service']);
+                  if (method_exists($factory, $definition['factory_method'])) {
+                    $backend = call_user_func_array(array($factory, $definition['factory_method']), $definition['arguments']);
+                    if ($backend instanceof CacheBackendInterface) {
+                      $backend->removeBin();
+                    }
+                  }
+                }
+                catch (Exception $e) {
+                  watchdog_exception('system', $e, 'Failed to remove cache bin defined by the service %id.', array('%id' => $id));
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
     watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
     $schema_store->delete($module);
     $disabled_config->clear($module);
diff --git a/core/lib/Drupal/Core/Cache/BackendChain.php b/core/lib/Drupal/Core/Cache/BackendChain.php
index d3fac6e..5df1a08 100644
--- a/core/lib/Drupal/Core/Cache/BackendChain.php
+++ b/core/lib/Drupal/Core/Cache/BackendChain.php
@@ -222,4 +222,14 @@ public function isEmpty() {
 
     return TRUE;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeBin() {
+    foreach ($this->backends as $backend) {
+      $this->removeBin();
+    }
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
index d38a094..a054604 100644
--- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
+++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
@@ -287,6 +287,11 @@ public function invalidateAll();
   public function garbageCollection();
 
   /**
+   * Remove a cache bin.
+   */
+  public function removeBin();
+
+  /**
    * Checks if a cache bin is empty.
    *
    * A cache bin is considered empty if it does not contain any valid data for
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 39359c3..4627d42 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Database\SchemaObjectExistsException;
 
 /**
  * Defines a default cache implementation.
@@ -69,7 +70,13 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) {
     // 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 = $this->connection->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . $this->connection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
+    $result = array();
+    try {
+      $result = $this->connection->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . $this->connection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
+    }
+    catch (\Exception $e) {
+      // Nothing to do.
+    }
     $cache = array();
     foreach ($result as $item) {
       $item = $this->prepareItem($item, $allow_invalid);
@@ -134,6 +141,32 @@ protected function prepareItem($cache, $allow_invalid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
+    // This is the first try.
+    $try = 1;
+    // Maximum one tries.
+    $max = 1;
+    // This loop is necessary to make sure any exceptions thrown in doSet()
+    // are propagated back with a proper backtrace. Putting the second doSet()
+    // within the catch would result in "Additional exception thrown while
+    // handling an exception".
+    do {
+      try {
+        $this->doSet($cid, $data, $expire, $tags);
+      }
+      catch (\Exception $e) {
+        if ($this->ensureBinExists()) {
+          // If the bin was just created, try one more time but only one more.
+          // By using try - max we avoid an infinite loop.
+          $max = 2;
+        }
+      }
+    } while ($try++ < $max);
+  }
+
+  /**
+   * Actually set the cache.
+   */
+  protected function doSet($cid, $data, $expire, $tags) {
     $flat_tags = $this->flattenTags($tags);
     $checksum = $this->checksumTags($flat_tags);
     $fields = array(
@@ -163,22 +196,25 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN
    * Implements Drupal\Core\Cache\CacheBackendInterface::delete().
    */
   public function delete($cid) {
-    $this->connection->delete($this->bin)
-      ->condition('cid', $cid)
-      ->execute();
+    $this->deleteMultiple(array($cid));
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
    */
   public function deleteMultiple(array $cids) {
-    // Delete in chunks when a large array is passed.
-    do {
-      $this->connection->delete($this->bin)
-        ->condition('cid', array_splice($cids, 0, 1000), 'IN')
-        ->execute();
+    try {
+      // Delete in chunks when a large array is passed.
+      do {
+        $this->connection->delete($this->bin)
+          ->condition('cid', array_splice($cids, 0, 1000), 'IN')
+          ->execute();
+      }
+      while (count($cids));
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
     }
-    while (count($cids));
   }
 
   /**
@@ -188,11 +224,16 @@ public function deleteTags(array $tags) {
     $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache');
     foreach ($this->flattenTags($tags) as $tag) {
       unset($tag_cache[$tag]);
-      $this->connection->merge('cache_tags')
-        ->insertFields(array('deletions' => 1))
-        ->expression('deletions', 'deletions + 1')
-        ->key(array('tag' => $tag))
-        ->execute();
+      try {
+        $this->connection->merge('cache_tags')
+          ->insertFields(array('deletions' => 1))
+          ->expression('deletions', 'deletions + 1')
+          ->key(array('tag' => $tag))
+          ->execute();
+      }
+      catch (\Exception $e) {
+        $this->catchException($e, 'cache_tags');
+      }
     }
   }
 
@@ -200,7 +241,12 @@ public function deleteTags(array $tags) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
   public function deleteAll() {
-    $this->connection->truncate($this->bin)->execute();
+    try {
+      $this->connection->truncate($this->bin)->execute();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
   }
 
   /**
@@ -214,28 +260,38 @@ public function invalidate($cid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalideMultiple().
    */
   public function invalidateMultiple(array $cids) {
-    // Update in chunks when a large array is passed.
-    do {
-      $this->connection->update($this->bin)
-        ->fields(array('expire' => REQUEST_TIME - 1))
-        ->condition('cid', array_splice($cids, 0, 1000), 'IN')
-        ->execute();
+    try {
+      // Update in chunks when a large array is passed.
+      do {
+        $this->connection->update($this->bin)
+          ->fields(array('expire' => REQUEST_TIME - 1))
+          ->condition('cid', array_splice($cids, 0, 1000), 'IN')
+          ->execute();
+      }
+      while (count($cids));
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
     }
-    while (count($cids));
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
    */
   public function invalidateTags(array $tags) {
-    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache');
-    foreach ($this->flattenTags($tags) as $tag) {
-      unset($tag_cache[$tag]);
-      $this->connection->merge('cache_tags')
-        ->insertFields(array('invalidations' => 1))
-        ->expression('invalidations', 'invalidations + 1')
-        ->key(array('tag' => $tag))
-        ->execute();
+    try {
+      $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+      foreach ($this->flattenTags($tags) as $tag) {
+        unset($tag_cache[$tag]);
+        $this->connection->merge('cache_tags')
+          ->insertFields(array('invalidations' => 1))
+          ->expression('invalidations', 'invalidations + 1')
+          ->key(array('tag' => $tag))
+          ->execute();
+      }
+    }
+    catch (\Exception $e) {
+      $this->catchException($e, 'cache_tags');
     }
   }
 
@@ -243,19 +299,31 @@ public function invalidateTags(array $tags) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
    */
   public function invalidateAll() {
-    $this->connection->update($this->bin)
-      ->fields(array('expire' => REQUEST_TIME - 1))
-      ->execute();
+    try {
+      $this->connection->update($this->bin)
+        ->fields(array('expire' => REQUEST_TIME - 1))
+        ->execute();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection().
    */
   public function garbageCollection() {
-    Database::getConnection()->delete($this->bin)
-      ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>')
-      ->condition('expire', REQUEST_TIME, '<')
-      ->execute();
+    try {
+      Database::getConnection()->delete($this->bin)
+        ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>')
+        ->condition('expire', REQUEST_TIME, '<')
+        ->execute();
+    }
+    catch (\Exception $e) {
+      // If the table does not exist, it surely does not have garbage in it.
+      // If the table exists, the next garbage collection will clean up.
+      // There is nothing to do.
+    }
   }
 
   /**
@@ -329,9 +397,160 @@ public function isEmpty() {
     $this->garbageCollection();
     $query = $this->connection->select($this->bin);
     $query->addExpression('1');
-    $result = $query->range(0, 1)
-      ->execute()
-      ->fetchField();
+    try {
+      $result = $query->range(0, 1)
+        ->execute()
+        ->fetchField();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
     return empty($result);
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeBin() {
+    try {
+      $this->connection->schema()->dropTable($this->bin);
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
+  }
+
+  /**
+   * Check if the cache bin exists and create it if not.
+   */
+  protected function ensureBinExists() {
+    try {
+      $database_schema = $this->connection->schema();
+      if (!$database_schema->tableExists($this->bin)) {
+        $schema_definition = $this->schemaDefinition();
+        $database_schema->createTable($this->bin, $schema_definition['bin']);
+        // If the bin doesn't exist, the cache tags table may also not exist.
+        if (!$database_schema->tableExists('cache_tags')) {
+          $database_schema->createTable('cache_tags', $schema_definition['cache_tags']);
+        }
+        return TRUE;
+      }
+    }
+    // If another process has already created the cache table, attempting to
+    // recreate it will throw an exception. In this case just catch the
+    // exception and do nothing.
+    catch (SchemaObjectExistsException $e) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Act on an exception when cache might be stale.
+   *
+   * If the cache_tags table does not yet exist, that's fine but if the table
+   * exists and yet the query failed, then the cache is stale and the
+   * exception needs to propagate.
+   *
+   * @param $e
+   *   The exception.
+   * @param string|null $table_name
+   *   The table name, defaults to $this->bin. Can be cache_tags.
+   */
+  protected function catchException(\Exception $e, $table_name = NULL) {
+    if ($this->connection->schema()->tableExists($table_name ?: $this->bin)) {
+      throw $e;
+    }
+  }
+
+  /**
+   * Defines the schema for the cache bin and cache_tags table.
+   */
+  public function schemaDefinition() {
+    $schema['bin'] = array(
+      'description' => 'Storage for the cache API.',
+      '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'),
+    );
+    $schema['cache_tags'] = 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'),
+    );
+    return $schema;
+  }
 }
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index ac83a06..4dba0ec 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -215,4 +215,10 @@ public function isEmpty() {
    */
   public function garbageCollection() {
   }
+
+ /**
+  * {@inheritdoc}
+  */
+  public function removeBin() {}
+
 }
diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php
index 16c0331..127101a 100644
--- a/core/lib/Drupal/Core/Cache/NullBackend.php
+++ b/core/lib/Drupal/Core/Cache/NullBackend.php
@@ -98,4 +98,9 @@ public function garbageCollection() {}
   public function isEmpty() {
     return TRUE;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeBin() {}
 }
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index 4fbba3b..73785fd 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -480,7 +480,7 @@ public function prepareComment($comment, $length = NULL) {
     // Truncate comment to maximum comment length.
     if (isset($length)) {
       // Add table prefixes before truncating.
-      $comment = truncate_utf8($this->connection->prefixTables($comment), $length, TRUE, TRUE);
+      $comment = substr($this->connection->prefixTables($comment), 0, $length);
     }
 
     return $this->connection->quote($comment);
diff --git a/core/modules/block/block.install b/core/modules/block/block.install
index b1fc925..01c5779 100644
--- a/core/modules/block/block.install
+++ b/core/modules/block/block.install
@@ -7,17 +7,6 @@
 use Drupal\Component\Uuid\Uuid;
 
 /**
- * Implements hook_schema().
- */
-function block_schema() {
-
-  $schema['cache_block'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_block']['description'] = 'Cache table for the Block module to store already built blocks, identified by module, delta, and various contexts which may change the block, such as theme, locale, and caching mode defined for the block.';
-
-  return $schema;
-}
-
-/**
  * Implements hook_install().
  */
 function block_install() {
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
index c1a1378..64833a5 100644
--- a/core/modules/field/field.install
+++ b/core/modules/field/field.install
@@ -9,16 +9,6 @@
 use Drupal\field\Plugin\Core\Entity\Field;
 
 /**
- * Implements hook_schema().
- */
-function field_schema() {
-  $schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_field']['description'] = 'Cache table for the Field module to store already built field informations.';
-
-  return $schema;
-}
-
-/**
  * Creates a field by writing directly to the database.
  *
  * @ingroup update_api
diff --git a/core/modules/filter/filter.install b/core/modules/filter/filter.install
index 536d4f6..45955ad 100644
--- a/core/modules/filter/filter.install
+++ b/core/modules/filter/filter.install
@@ -8,16 +8,6 @@
 use Drupal\Component\Uuid\Uuid;
 
 /**
- * Implements hook_schema().
- */
-function filter_schema() {
-  $schema['cache_filter'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_filter']['description'] = 'Cache table for the Filter module to store already filtered pieces of text, identified by text format and hash of the text.';
-
-  return $schema;
-}
-
-/**
  * @addtogroup updates-7.x-to-8.x
  * @{
  */
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
index 4d28fa6..81d5321 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
@@ -143,8 +143,7 @@ function testFilterAdmin() {
     $this->drupalGet('admin/config/content/formats/' . $basic);
     $this->assertFieldByName('filters[filter_html][settings][allowed_html]', $edit['filters[filter_html][settings][allowed_html]'], 'Allowed HTML tag added.');
 
-    $result = db_query('SELECT * FROM {cache_filter}')->fetchObject();
-    $this->assertFalse($result, 'Cache cleared.');
+    $this->assertTrue(cache('filter')->isEmpty(), 'Cache cleared.');
 
     $elements = $this->xpath('//select[@name=:first]/following::select[@name=:second]', array(
       ':first' => 'filters[' . $first_filter . '][weight]',
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php
index f7a6c65..3b607a5 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php
@@ -40,17 +40,4 @@ protected function createCacheBackend($bin) {
     return new DatabaseBackend($this->container->get('database'), $bin);
   }
 
-  /**
-   * Installs system schema.
-   */
-  public function setUpCacheBackend() {
-    $this->installSchema('system', array('cache', 'cache_page', 'cache_tags', 'cache_path', 'cache_bootstrap'));
-  }
-
-  /**
-   * Uninstalls system schema.
-   */
-  public function tearDownCacheBackend() {
-    drupal_uninstall_schema('system');
-  }
 }
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 13aa535..67e05d0 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1934,12 +1934,12 @@ function hook_mail($key, &$message, $params) {
 /**
  * Flush all persistent and static caches.
  *
- * This hook asks your module to clear all of its persistent (database) and
- * static caches, in order to ensure a clean environment for subsequently
+ * This hook asks your module to clear all of its static caches,
+ * in order to ensure a clean environment for subsequently
  * invoked data rebuilds.
  *
  * Do NOT use this hook for rebuilding information. Only use it to flush custom
- * caches and return the names of additional cache bins to flush.
+ * caches.
  *
  * Static caches using drupal_static() do not need to be reset manually.
  * However, all other static variables that do not use drupal_static() must be
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 493db9b..e23bf8e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -597,102 +597,6 @@ function system_schema() {
     ),
   );
 
-  $schema['cache_tags'] = 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'),
-  );
-
-  $schema['cache'] = array(
-    'description' => 'Generic cache table for caching things not separated out into their own tables. Contributed modules may also use this to store cached items.',
-    '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'),
-  );
-  $schema['cache_bootstrap'] = $schema['cache'];
-  $schema['cache_bootstrap']['description'] = 'Cache table for data required to bootstrap Drupal, may be routed to a shared memory cache.';
-  $schema['cache_config'] = $schema['cache'];
-  $schema['cache_config']['description'] = 'Cache table for configuration data.';
-  $schema['cache_page'] = $schema['cache'];
-  $schema['cache_page']['description'] = 'Cache table used to store compressed pages for anonymous users, if page caching is enabled.';
-  $schema['cache_menu'] = $schema['cache'];
-  $schema['cache_menu']['description'] = 'Cache table for the menu system to store router information as well as generated link trees for various menu/page/user combinations.';
-  $schema['cache_path'] = $schema['cache'];
-  $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
-
   $schema['flood'] = array(
     'description' => 'Flood controls the threshold of events, such as the number of contact attempts.',
     'fields' => array(
diff --git a/core/modules/system/tests/modules/cache_test/cache_test.install b/core/modules/system/tests/modules/cache_test/cache_test.install
deleted file mode 100644
index 5b50e11..0000000
--- a/core/modules/system/tests/modules/cache_test/cache_test.install
+++ /dev/null
@@ -1,15 +0,0 @@
-<?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/toolbar/toolbar.install b/core/modules/toolbar/toolbar.install
index dc65611..6732bb9 100644
--- a/core/modules/toolbar/toolbar.install
+++ b/core/modules/toolbar/toolbar.install
@@ -6,35 +6,17 @@
  */
 
 /**
- * Implements hook_schema().
- */
-function toolbar_schema() {
-  $schema['cache_toolbar'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_toolbar']['description'] = 'Cache table for the Toolbar module to store per-user hashes of rendered toolbar subtrees.';
-  return $schema;
-}
-
-/**
  * @addtogroup updates-7.x-to-8.x
  * @{
  */
 
 /**
- * Creates the {cache_toolbar} cache table.
- */
-function toolbar_update_8000() {
-  $schema['cache_toolbar'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_toolbar']['description'] = 'Cache table for the Toolbar module to store per-user hashes of rendered toolbar subtrees.';
-  db_create_table('cache_toolbar', $schema['cache_toolbar']);
-}
-
-/**
  * Enable the Breakpoint and Config modules.
  *
  * The 7.x version of the Toolbar module had no dependencies. The 8.x version
  * depends on the Breakpoint and Configuration manager modules.
  */
-function toolbar_update_8001() {
+function toolbar_update_8000() {
   // Enable the modules without re-installing the schema.
   update_module_enable(array('breakpoint'));
 }
diff --git a/core/modules/views/views.install b/core/modules/views/views.install
index 8bda10e..aea8d0c 100644
--- a/core/modules/views/views.install
+++ b/core/modules/views/views.install
@@ -15,19 +15,6 @@ function views_install() {
 }
 
 /**
- * Implements hook_schema().
- */
-function views_schema() {
-  $schema['cache_views_info'] = drupal_get_schema_unprocessed('system', 'cache');
-
-  $schema['cache_views_results'] = drupal_get_schema_unprocessed('system', 'cache');
-  $schema['cache_views_results']['description'] = 'Cache table for views to store pre-rendered queries, results, and display output.';
-  $schema['cache_views_results']['fields']['serialized']['default'] = 1;
-
-  return $schema;
-}
-
-/**
  * Provide an initial schema.
  *
  * @see update_module_enable().
