Opened 4 months ago
Last modified 3 months ago
#61467 new defect (bug)
Inconsistent cache handling for network (site) meta
Reported by: | xParham | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | major | Version: | |
Component: | Cache API | Keywords: | has-testing-info dev-feedback |
Focuses: | multisite, performance | Cc: |
Description
It appears that there are multiple ways to work with wp_sitemeta
and each use different cache keys and groups, resulting in inconsistent behavior and out-of-sync cached values.
One method is using update_site_option()
/update_network_option()
which uses "$network_id:$option"
for the cache key, and site-options
for the group.
The other method is update_metadata( 'site', ... )
which uses the object ID (here the network ID) for the cache key, and site_meta
for the cache group.
Normally, in the code, we use update_site_option()
/update_network_option()
, however, WP CLI's wp network meta ...
uses the *_metadata()
functions, and when using both we end up with out of sync cached values.
Steps to reproduce the issue via WP CLI:
wp eval 'update_network_option( 1, "mykey", "123" );' wp eval 'echo get_network_option( 1, "mykey" );' #Displays 123 wp network meta update 1 mykey 456 wp network meta get 1 mykey #Displays 456 wp eval 'echo get_network_option( 1, "mykey" );' #Still displays 123, but 456 is the expected value
Change History (8)
#3
@
4 months ago
@narenin Thanks for confirming this. I understand the workaround you have suggested, but I believe this should be fixed at the core level. The core should pick one method for working with wp_sitemeta
and stick to it everywhere.
Perhaps in update_metadata()
it can check if $meta_type === 'site'
and then just bail early with a return update_network_option( $object_id, $meta_key, $meta_value );
, and similarly in other *_metadata()
functions. Or the other way, change update_network_option()
to let update_metadata()
handle the update.
#4
@
4 months ago
Hi,
It could be like this.
<?php // Modify update_metadata function function update_metadata($meta_type, $object_id, $meta_key, $meta_value) { if ($meta_type === 'site') { return update_network_option($object_id, $meta_key, $meta_value); } // Existing code for other meta types... // Example of existing metadata handling code: // return update_meta($meta_type, $object_id, $meta_key, $meta_value); } // Modify update_network_option function function update_network_option($network_id, $option_name, $newvalue) { // Call update_metadata to handle the update return update_metadata('site', $network_id, $option_name, $newvalue); } // Function to synchronize caches function sync_network_option_and_meta($network_id, $key, $value) { // Update the option update_network_option($network_id, $key, $value); // Clear both caches to ensure consistency wp_cache_delete("$network_id:$key", 'site-options'); wp_cache_delete($network_id, 'site_meta'); } // Example usage in WP CLI wp eval 'sync_network_option_and_meta(1, "mykey", "456");'
#5
@
4 months ago
There was a ticket #37181 that was designed to get the *_network_option to use metadata api. However, this was merged in [54080] and reverted in [54637], it is generated performance regressions.
This issue how how WP CLI implements network options, not how core does it. A ticket should be created on the WP CLI repo.
#6
@
3 months ago
@xParham Reported upstream. https://github.com/wp-cli/entity-command/issues/504
#7
@
3 months ago
I think this should be resolved in WP Core. The problem is that the name of the tables used suggest that get_metadata( 'site', 1, 'siteurl', true )
is an appropriate way of getting the option. And the code works as expected.
It also presents a problem that it is possible to add duplicate options to the table using code such as add_metadata( 'site', 1, 'siteurl', '61467' )
. Once such code is run, the option returned by get_site_option()
will vary depending on the database engine being used.
Calls to update_site_option()
once that happens can behave very strangely indeed. In my case update_site_option( 'siteurl', 'testing' )
returned true
but the second copy of the option was updated to the value of the first.
Hi @xParham ,
I am also able to replicate the same issue. The issue arises from the inconsistent use of different WordPress functions for updating site (network) options and metadata. These different functions use distinct caching mechanisms, leading to out-of-sync values between
update_network_option()
/get_network_option()
andupdate_metadata()
/get_metadata()
.Understanding the Functions and Their Cache Groups
update_site_option()
/update_network_option()
:Cache Key: $network_id:$option
Cache Group: site-options
Usage: Typically used for storing network-wide options.
update_metadata('site', ...):
Cache Key: $object_id (where $object_id is the network ID)
Cache Group: site_meta
Usage: Typically used for more granular metadata associated with the site (network).
Why This Happens
When you update a network option using update_network_option(), it sets a value in the site-options cache group. However, if you then update the same value using
update_metadata('site', ...)
, it sets a value in the site_meta cache group, bypassing the site-options cache group.This discrepancy means that
get_network_option()
may retrieve stale data because it checks the site-options cache group, which hasn't been updated byupdate_metadata('site', ...)
.Steps to Reproduce
Set value using
update_network_option()
:Cache Key: 1:mykey in site-options
Retrieve value
using get_network_option()
:Output: 123
Set value using
update_metadata('site', ...)
:Cache Key: 1 in site_meta
Retrieve value using
get_metadata('site', ...)
:Output: 456
Retrieve value again using
get_network_option()
:Output: 123 (still, because the site-options cache was not updated)
Solution: Invalidate Caches
One solution to ensure consistency is to manually invalidate or update both caches when you change a network option or metadata.
Example Code to Synchronize Caches:
Usage in WP CLI
Ensuring Consistency in WP CLI Scripts
When writing WP CLI scripts or commands, ensure that any update to a network option also updates the corresponding metadata and clears the relevant caches.
WP CLI Command Example
By ensuring that both the network option and site meta are updated and their respective caches are cleared, we can maintain consistent and synchronized values across our WordPress network.