从插件收集和记录数据:如何在没有竞争条件的情况下做到这一点?

时间:2021-09-16 作者:O. Jones

我需要在WordPress插件中捕获数据并将其附加到某种日志中。

我想要的数据恰好是来自$wpdb的慢速SQL查询->;查询。我希望能介绍一些有用的东西;脏打“;SQL查询给我的用户,以帮助他们进行优化。它是一个配套插件,或者是一个功能集this plugin. (我知道这种系统检测的性能问题。捕获会话的持续时间将受到限制等)

在每个相关的页面视图中,我将捕获一些数据并记录下来。之后,我的插件将检索、处理和删除日志。如何以WordPress友好的方式进行数据捕获?

我在考虑用瞬变脉冲来保持原木。我正在使用过期瞬态,希望避免未处理的日志累积。我的数据流看起来像这样(伪代码)。

$logdata = get_transient( $tName );
$logdata .= $newdata;
set_transient( $tName, $logdata, 86400 );
但是,在繁忙的站点上,多个php实例将相互竞争。一个实例将执行其get_transient(), 然后,另一个实例将在第一个实例执行其设置之前执行其get。因此,其中一个实例的数据将丢失。

如果要使用与MyISAM兼容的普通老SQL执行此操作,我会执行以下操作:

UPDATE wp_options WHERE option_name=\'tname\' SET option_value = option_value + \'newvalue\'
这避免了可能的竞争条件。如果有一个append_transient($name, $val, $timeout) 函数来执行此操作。

我也可以把桌子锁上,但那太粗鲁了。

如果我知道我的插件位于数据库中包含InnoDB的站点上,我可以使用SQL事务。但我不知道。

Is there a better way?

2 个回复
最合适的回答,由SO网友:Mark Kaplun 整理而成

可以使用创建锁flock 在一个现有文件上(或为此创建一个特殊文件)。在开始canculation之前获取锁,并在存储结果后释放它。

SO网友:O. Jones

我终于用这个函数解决了我的问题。它以竞争条件安全的方式附加到MySQL数据库中的瞬态。

/** Upsert and append data to a WordPress transient.
 * This function deletes the transient from the WordPress options cache to avoid stale data.
 * @param string $transient Transient name.
 * @param string $value Data to append.
 * @param int $expiration Transient expiration (default 120 sec). 0 means the transient does not expire.
 * @param string $separator Separator between appended values (default \'|||\').
 * @param int $maxlength Stop appending when value reaches this length to avoid bloat (default 512 KiB).
 */
function append_to_transient( $transient, $value, $expiration = 120, $separator = \'|||\', $maxlength = 524288 ) {
    if ( ! $transient || strlen( $transient ) === 0 ) return;
    if ( ! $value ) return;
    try {
        global $wpdb;
        if ( $expiration ) {
            $name = \'_transient_timeout_\' . $transient;
            wp_cache_delete( $name, \'options\' );
            $query = "INSERT IGNORE INTO $wpdb->options (option_name, option_value, autoload) VALUES (%s, %d, \'no\')";
            $query = $wpdb->prepare( $query, $name, $expiration + time() );
            $wpdb->get_results( $query );
        }
        $name = \'_transient_\' . $transient;
        wp_cache_delete( $name, \'options\' );
        $wpdb->get_results( $wpdb->prepare( "SET @upload = %s", $value ) );
        $query = "INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES (%s, @upload, \'no\')"
                 . "ON DUPLICATE KEY UPDATE option_value ="
                 . "IF(%d > 0 AND LENGTH(option_value) <= %d - LENGTH(@upload),"
                 . "CONCAT(option_value, %s, @upload), option_value)";
        $query = $wpdb->prepare( $query, $name, $maxlength, $maxlength, $separator );
        $wpdb->get_results( $query );
    } catch ( Exception $e ) {
        /* empty, intentionally, don\'t crash when logging fails */
    }
}

相关推荐

Modifying WordPress plugins

关于对WordPress插件进行更改,我有一个非常简单的问题。我为我的问题的简单性道歉,因为我对使用开源代码和插件开发新手非常陌生。我发现了一个插件,它为我正在进行的一个项目提供了一个很好的解决方案。然而,为了更好地满足我的需要,我修改了代码。插件有一个;GPLv2或更高版本“;许可证,基于this 似乎是说对插件的修改很好,只要我注意到我所做的任何更改,并将插件发布在;GPLv2或更高版本“;许可证也是。由于我对插件所做的修改,我希望能够将其作为客户端工作的一部分提供给其他人。然而,我不确定前进的最佳方