[wp-trac] [WordPress Trac] #34304: get_and_update_post_meta for atomic post meta operations
WordPress Trac
noreply at wordpress.org
Wed Oct 14 19:49:54 UTC 2015
#34304: get_and_update_post_meta for atomic post meta operations
-----------------------------+-----------------------------
Reporter: lpghatguy | Owner:
Type: feature request | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Database | Version: trunk
Severity: normal | Keywords:
Focuses: |
-----------------------------+-----------------------------
Assuming I have a function on the server that pulls post meta using
`get_post_meta` and then writes it back, there's a relatively wide window
for another request to compete with database resources and write an
incorrect value.
I'm going to call this function F, separated into two parts, read (R) and
write (W). The result of F depends on the current value of the meta.
As an example, say that I have two requests, R1 and R2, both competing to
perform operation F. Ideally, this would happen like so:
R1: R
R1: W
R2: R
R2: W
In the wild, sometimes an awful race happens:
R1: R
R2: R
R1: W
R2: W
This can result in a catastrophically wrong value written to the database
(usually as if request R1 never happened). What I'm proposing is a way to
lock a specific row (or piece of post meta) for a defined period of time.
The model of flow would then change to the following:
R1: R & lock
R1: W & release lock
R2: R & lock
R2: W & release lock
In this case, '&' denotes that the operation should be totally atomic (one
database query).
A possible API for this might be:
{{{
get_and_update_post_meta($postID, $metaName, $callback);
}}}
Then, assuming PHP 5.4 or newer, it could be used to create an atomic
increment operation like so:
{{{
get_and_update_post_meta($ID, "some_meta_field", function($value) {
return parseInt($value) + 1;
});
}}}
In older PHP releases, this could be done with a predefined function and a
string-based function name.
As far as implementation goes, MySQL 5.0+ supports GET_LOCK, RELEASE_LOCK,
and IS_FREE_LOCK (http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-
functions.html#function_get-lock) that would be perfect for this purpose.
`get_and_update_post_meta` would be functionally equivalent to the
following two:
1. IS_FREE_LOCK & GET_LOCK & `get_post_meta`
2. RELEASE_LOCK & `update_post_meta`
The reasoning for the callback is to prevent accidental locks without
corresponding unlocks. Other systems totally unrelated to WordPress use a
similar model, like LOVE: https://love2d.org/wiki/Channel:performAtomic
--
Ticket URL: <https://core.trac.wordpress.org/ticket/34304>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list