diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 44a4111..e4abd82 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -48,9 +53,6 @@ class DatabaseBackend implements CacheBackendInterface {
    */
   function getMultiple(&$cids) {
     try {
-      // Garbage collection necessary when enforcing a minimum cache lifetime.
-      $this->garbageCollection($this->bin);
-
       // When serving cached pages, the overhead of using db_select() was found
       // to add around 30% overhead to the request. Since $this->bin is a
       // variable, this means the call to db_query() here uses a concatenated
@@ -90,8 +92,6 @@ class DatabaseBackend implements CacheBackendInterface {
    *   valid item to load.
    */
   protected function prepareItem($cache) {
-    global $user;
-
     if (!isset($cache->data)) {
       return FALSE;
     }
@@ -113,10 +113,31 @@ class DatabaseBackend implements CacheBackendInterface {
     return $cache;
   }
 
+  protected function cleanSession() {
+    $cache_lifetime = config('system_performance')->get('cache_lifetime');
+    // Clean-up the per-user cache expiration session data, so that the session
+    // handler can properly clean-up the session data for anonymous users.
+    if (isset($_SESSION['cache_expiration'])) {
+      $expire = REQUEST_TIME - $cache_lifetime;
+      foreach ($_SESSION['cache_expiration'] as $bin => $timestamp) {
+        if ($timestamp < $expire) {
+          unset($_SESSION['cache_expiration'][$bin]);
+        }
+      }
+      if (!$_SESSION['cache_expiration']) {
+        unset($_SESSION['cache_expiration']);
+      }
+    }
+  }
+ 
+
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   function set($cid, $data, $expire = CACHE_PERMANENT) {
+    // When setting cache items, clean up old session data in case it's
+    // stale.
+    $this->cleanSession();
     $fields = array(
       'serialized' => 0,
       'created' => REQUEST_TIME,
@@ -184,29 +205,22 @@ class DatabaseBackend implements CacheBackendInterface {
    * Implements Drupal\Core\Cache\CacheBackendInterface::expire().
    */
   function expire() {
-    if (variable_get('cache_lifetime', 0)) {
-      // We store the time in the current user's session. We then simulate
-      // that the cache was flushed for this user by not returning cached
-      // data that was cached before the timestamp.
-      $_SESSION['cache_expiration'][$this->bin] = REQUEST_TIME;
-
-      $cache_flush = variable_get('cache_flush_' . $this->bin, 0);
-      if ($cache_flush == 0) {
-        // This is the first request to clear the cache, start a timer.
-        variable_set('cache_flush_' . $this->bin, REQUEST_TIME);
-      }
-      elseif (REQUEST_TIME > ($cache_flush + variable_get('cache_lifetime', 0))) {
-        // Clear the cache for everyone; cache_lifetime seconds have passed
-        // since the first request to clear the cache.
-        db_delete($this->bin)
-          ->condition('expire', CACHE_PERMANENT, '<>')
-          ->condition('expire', REQUEST_TIME, '<')
-          ->execute();
-        variable_set('cache_flush_' . $this->bin, 0);
-      }
-    }
-    else {
-      // No minimum cache lifetime, flush all temporary cache entries now.
+    if ($cache_lifetime = config('system.performance')->get('cache_lifetime')) {
+      // Clear expired items from the cache. 
+      db_delete($this->bin) 
+        ->condition('expire', CACHE_PERMANENT, '>') 
+        ->condition('expire', REQUEST_TIME, '<') 
+        ->execute(); 
+      variable_set('cache_flush_' . $this->bin, 0); 
+ 
+      // Clear CACHE_TEMPORARY items that are older than the minimum cache lifetime. 
+      db_delete($this->bin) 
+        ->condition('expire', CACHE_TEMPORARY) 
+        ->condition('created', REQUEST_TIME - $cache_lifetime, '<') 
+        ->execute(); 
+     } 
+     else { 
+      // No minimum cache lifetime, flush all expired and temporary cache entries now. 
       db_delete($this->bin)
         ->condition('expire', CACHE_PERMANENT, '<>')
         ->condition('expire', REQUEST_TIME, '<')
@@ -219,38 +233,23 @@ class DatabaseBackend implements CacheBackendInterface {
    */
   function garbageCollection() {
     $cache_lifetime = config('system.performance')->get('cache_lifetime');
+    $config = config('system.performance');
 
-    // Clean-up the per-user cache expiration session data, so that the session
-    // handler can properly clean-up the session data for anonymous users.
-    if (isset($_SESSION['cache_expiration'])) {
-      $expire = REQUEST_TIME - $cache_lifetime;
-      foreach ($_SESSION['cache_expiration'] as $bin => $timestamp) {
-        if ($timestamp < $expire) {
-          unset($_SESSION['cache_expiration'][$bin]);
-        }
-      }
-      if (!$_SESSION['cache_expiration']) {
-        unset($_SESSION['cache_expiration']);
-      }
-    }
+    // Clear expired items from the cache.
+    db_delete($this->bin)
+      ->condition('expire', CACHE_PERMANENT, '>')
+      ->condition('expire', REQUEST_TIME, '<')
+      ->execute();
 
-    // Garbage collection of temporary items is only necessary when enforcing
-    // a minimum cache lifetime.
-    if (!$cache_lifetime) {
-      return;
-    }
-    // When cache lifetime is in force, avoid running garbage collection too
-    // often since this will remove temporary cache items indiscriminately.
-    $cache_flush = variable_get('cache_flush_' . $this->bin, 0);
-    if ($cache_flush && ($cache_flush + $cache_lifetime <= REQUEST_TIME)) {
-      // Reset the variable immediately to prevent a meltdown in heavy load situations.
-      variable_set('cache_flush_' . $this->bin, 0);
-      // Time to flush old cache data
-      db_delete($this->bin)
-        ->condition('expire', CACHE_PERMANENT, '<>')
-        ->condition('expire', $cache_flush, '<=')
-        ->execute();
-    }
+    // Clear old temporary cache items, 'old' is defined as older than the
+    // minimum cache lifetime, or 24 hours, whichever is the greatest.
+    $old = max($cache_lifetime, 86400);
+
+    // Clear CACHE_TEMPORARY items that are older than the minimum cache lifetime.
+    db_delete($this->bin)
+      ->condition('expire', CACHE_TEMPORARY)
+      ->condition('created', REQUEST_TIME - $old, '<')
+      ->execute();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php
index 53f9b23..d3d31c7 100644
--- a/core/lib/Drupal/Core/Cache/InstallBackend.php
+++ b/core/lib/Drupal/Core/Cache/InstallBackend.php
@@ -32,6 +32,12 @@ use Exception;
  * administrator cleared the cache manually.
  */
 class InstallBackend extends DatabaseBackend {
+  function __construct($bin) {
+    if ($bin != 'cache') {
+      $bin = 'cache_' . $bin;
+    }
+    $this->bin = $bin;
+  }
 
   /**
    * Overrides Drupal\Core\Cache\CacheBackendInterface::get().
diff --git a/core/modules/simpletest/tests/cache.test b/core/modules/simpletest/tests/cache.test
index 7040aef..b0be011 100644
--- a/core/modules/simpletest/tests/cache.test
+++ b/core/modules/simpletest/tests/cache.test
@@ -317,6 +317,41 @@ class CacheClearCase extends CacheTestCase {
   }
 
   /**
+   * Test CACHE_TEMPORARY behaviour.
+   */
+  function testCacheTemporary() {
+    $cache = cache($this->default_bin);
+    // Set a permanent and temporary cache item.
+    $cache->set('test_cid_clear1', $this->default_value, CACHE_TEMPORARY);
+    $cache->set('test_cid_clear2', $this->default_value);
+    $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value));
+    $this->assertTrue($this->checkCacheExists('test_cid_clear2', $this->default_value));
+
+    // Expire all items in the bin, only the temporary item should be removed.
+    $cache->expire();
+    $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value));
+    $this->assertTrue($this->checkCacheExists('test_cid_clear2', $this->default_value));
+
+    // Set the temporary item again.
+    $cache->set('test_cid_clear1', $this->default_value, CACHE_TEMPORARY);
+
+    // Now call the garbageCollection method, neither item should be removed.
+    $cache->garbageCollection();
+    $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value));
+    $this->assertTrue($this->checkCacheExists('test_cid_clear2', $this->default_value));
+
+    // Set a minimum cache lifetime.
+    $cache->set('test_cid_clear1', $this->default_value, CACHE_TEMPORARY);
+    $this->setUpLifetime(300);
+
+    // Now after expiring the bin, neither the temporary nor permanent item
+    // should be removed.
+    $cache->expire();
+    $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value));
+    $this->assertTrue($this->checkCacheExists('test_cid_clear2', $this->default_value));
+  }
+
+  /**
    * Test drupal_flush_all_caches().
    */
   function testFlushAllCaches() {
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 905d11d..1282d31 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -682,7 +682,7 @@ function system_schema() {
       ),
     ),
     'indexes' => array(
-      'expire' => array('expire'),
+      'expire_created' => array('expire', 'created'),
     ),
     'primary key' => array('cid'),
   );
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 94fd3e0..833d2da 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3056,7 +3056,7 @@ function system_cron() {
   $core = array('cache', 'path', 'filter', 'page', 'form', 'menu');
   $cache_bins = array_merge(module_invoke_all('flush_caches'), $core);
   foreach ($cache_bins as $bin) {
-    cache($bin)->expire();
+    cache($bin)->garbageCollection();
   }
 
   // Cleanup the batch table and the queue for failed batches.
