Gathering and logging data from a plugin: how to do it without race conditions?
I have a need to capture data in a WordPress plugin and append it into some sort of log.
The data I want happens to be slow SQL queries from $wpdb-queries. I'm hoping to present useful dirty dozen SQL queries to my users to help them with optimizations. It's a companion plugin, or maybe a feature set, for this plugin. (I'm aware of the performance issues around this kind of system instrumentation. Capture sessions will be limited in duration. Etc.)
In each relevant pageview I will capture some data and log it. Then later my plugin will retrieve, process, and delete the log. How can I do this data capture in a WordPress-friendly way?
I'm thinking of using a transient to hold the log. I'm using expiring transients in my hope to avoid unprocessed logs from accumulating. My data flow would look something like this (pseudocode).
$logdata = get_transient( $tName );
$logdata .= $newdata;
set_transient( $tName, $logdata, 86400 );
But, on a busy site multiple php instances will race each other. One instance will do its get_transient()
, then another instance will do its get before the first instance does its set. So one of the instances' data will be lost.
If I were to do this with plain old MyISAM-compatible SQL I'd do something like this:
UPDATE wp_options WHERE option_name='tname' SET option_value = option_value + 'newvalue'
That avoids the possible race condition. It would be great if there were an append_transient($name, $val, $timeout)
function to do this operation.
I could also lock the table, but that would be really rude.
If I knew my plugin was on a site with InnoDB in its database I could use an SQL transaction. But I don't know that.
Is there a better way?