Opened 8 years ago
Last modified 5 months ago
#40052 new defect (bug)
Issue with WP_Cache not invalidating stale cache after an update request
Reported by: | cookiesowns | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | major | Version: | 4.7.3 |
Component: | Cache API | Keywords: | |
Focuses: | administration, performance | Cc: |
Description
Hi,
There appears to be an issue with WP_Cache if/when an object-cache has a stale value, and you attempt to update that value to the value that already exists in the database ( race condition as an example ). The object-cache in this case will never be invalidated until the TTL is hit, or if/when the cache is flushed.
This affects high volume sites that has repetitive actions.
An example of this happens on our site in production on user_meta, where quick endpoints fire that requires a set value on user_meta, however occasionally redis-cache will not get updated with the new value, even though the wp database does have the proper value.
In this case there's an infinite loop where wp_cache will return the old stale value, and the code will correctly attempt to update it to the new value, but WP thinks the value is already correct, and thus the object-cache will not be updated.
Potentially related bugs are #26779 & #31245
An easy solution is to add a wp_cache_delete onto lines 195/196 here: https://github.com/WordPress/WordPress/blob/master/wp-includes/meta.php#L190-L253
Just an update to this comment for accuracy ( I wish I could update the original post )
It seems I was a bit overzealous with my initial discovery / debugging... Was just quickly skimming through code that seems similar to the behavior I was seeing in our environment.. the LOC's I posted could potentially be related, but I don't think it's the core culprit.
After some additional reading, I believe https://github.com/WordPress/WordPress/blob/master/wp-includes/meta.php#L247-L251 to be the culprit of the issue.
Reasoning:
If for whatever reason wp_cache_delete fails on an update request and the cache was previously populated, the cache is now invalid and will return stale data.
Because the meta_update call requires the previous value to be accurate in order for the MySQL WHERE statement to work, the future update request will not go through thus never invalidating the cache anymore.