diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index 73c7139..04a941d 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -48,9 +48,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 @@ -185,30 +182,28 @@ class DatabaseBackend implements CacheBackendInterface { * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). */ function expire() { - if (variable_get('cache_lifetime', 0)) { + if ($cache_lifetime = variable_get('cache_lifetime', 0)) { // We store the time in the current user's $user->cache variable which // will be saved into the sessions bin by _drupal_session_write(). We then // simulate that the cache was flushed for this user by not returning // cached data that was cached before the timestamp. $GLOBALS['user']->cache = 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); - } + // 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 temporary cache entries now. + // No minimum cache lifetime, flush all expired and temporary cache entries now. db_delete($this->bin) ->condition('expire', CACHE_PERMANENT, '<>') ->condition('expire', REQUEST_TIME, '<') @@ -222,18 +217,7 @@ class DatabaseBackend implements CacheBackendInterface { function garbageCollection() { global $user; - // 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 + variable_get('cache_lifetime', 0) <= 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(); - } + $this->expire(); } /** diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 2cbb615..283f5b3 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 469f996..761ef5a 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -3057,7 +3057,17 @@ 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(); + // If the cache backend provides a garbageCollection() method, call that. + // If it does not, expire all temporary and expired cache items. Limit + // these calls to once every 24 hours by default to avoid wiping the page + // and block caches every cron run. + $cache = cache($bin); + $name = 'cache_garbage_collect_' . $bin; + $window = max(variable_get('cache_lifetime', 0), variable_get('cache_garbage_collection_frequency', 86400)); + if (flood_is_allowed($name, 1, $window, 'cron')) { + flood_register_event($name, 1, $window, 'cron'); + $cache->garbageCollection(); + } } // Cleanup the batch table and the queue for failed batches.