Woocommerce/WordPress 和 ACID

据我所知,WordPress 在查询数据库时不使用事务。查看 Woocommerce 源代码后,看起来 Woocommerce 也没有。我的问题之一是:为处理货币交易(订单和支付)而构建的应用程序如何不依赖于 ACID?在没有事务的情况下运行会使隔离级别无用,或者不是吗?为应用程序中的各种不当行为(脏读/写、读/写倾斜、幻读)敞开大门。

我想剖析 Woocommerce 中创建订单功能的一部分,也许有人可以阐明 Woocommerce 如何在没有 ACID 的情况下每分钟可靠地处理数千个订单交易。

天空是极限。我们已经看到商店列出了 100,000 多种产品,每分钟处理数千笔交易。在这些情况下,他们拥有出色的托管支持和专注于优化的自己的开发团队。

来源:https://docs.woocommerce.com/document/woocommerce-scaling-faqs/

从现在开始,我将粘贴下面的代码来帮助说明我的思考过程,但请参考实际来源(链接)中的行号。每个来源都将被赋予一个名称。谢谢。

让我们看一个简单的例子,其中 Woocommerce 循环更新多个 post_meta

这一切都始于 create() 函数。

/**
 * Method to create a new order in the database.
 *
 * @param WC_Order $order Order object.
 */
public function create( &$order ) {
    $order->set_version( Constants::get_constant( 'WC_VERSION' ) );
    $order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() );
    if ( ! $order->get_date_created( 'edit' ) ) {
        $order->set_date_created( time() );
    }

    $id = wp_insert_post(
        apply_filters(
            'woocommerce_new_order_data',array(
                'post_date'     => gmdate( 'Y-m-d H:i:s',$order->get_date_created( 'edit' )->getOffsetTimestamp() ),'post_date_gmt' => gmdate( 'Y-m-d H:i:s',$order->get_date_created( 'edit' )->getTimestamp() ),'post_type'     => $order->get_type( 'edit' ),'post_status'   => $this->get_post_status( $order ),'ping_status'   => 'closed','post_author'   => 1,'post_title'    => $this->get_post_title(),'post_password' => $this->get_order_key( $order ),'post_parent'   => $order->get_parent_id( 'edit' ),'post_excerpt'  => $this->get_post_excerpt( $order ),)
        ),true
    );

    if ( $id && ! is_wp_error( $id ) ) {
        $order->set_id( $id );
        $this->update_post_meta( $order );
        $order->save_meta_data();
        $order->apply_changes();
        $this->clear_caches( $order );
    }
}

来源 1:https://woocommerce.github.io/code-reference/files/woocommerce-includes-data-stores-abstract-wc-order-data-store-cpt.html#source-view.58

在第 86 行 (SOURCE1) 上,我们调用 $this->update_post_meta( $order );,我假设调用它是为了更新数据库中的 post_meta 表。这是功能:

/**
 * Helper method that updates all the post meta for an order based on it's settings in the WC_Order class.
 *
 * @param WC_Order $order Order object.
 * @since 3.0.0
 */
protected function update_post_meta( &$order ) {
    $updated_props     = array();
    $meta_key_to_props = array(
        '_order_currency'     => 'currency','_cart_discount'      => 'discount_total','_cart_discount_tax'  => 'discount_tax','_order_shipping'     => 'shipping_total','_order_shipping_tax' => 'shipping_tax','_order_tax'          => 'cart_tax','_order_total'        => 'total','_order_version'      => 'version','_prices_include_tax' => 'prices_include_tax',);

    $props_to_update = $this->get_props_to_update( $order,$meta_key_to_props );

    foreach ( $props_to_update as $meta_key => $prop ) {
        $value = $order->{"get_$prop"}( 'edit' );
        $value = is_string( $value ) ? wp_slash( $value ) : $value;

        if ( 'prices_include_tax' === $prop ) {
            $value = $value ? 'yes' : 'no';
        }

        $updated = $this->update_or_delete_post_meta( $order,$meta_key,$value );

        if ( $updated ) {
            $updated_props[] = $prop;
        }
    }

    do_action( 'woocommerce_order_object_updated_props',$order,$updated_props );
}

来源 2:https://woocommerce.github.io/code-reference/files/woocommerce-includes-data-stores-abstract-wc-order-data-store-cpt.html#source-view.318

好的,在第 334 行 (SOURCE2) 上运行一个循环,这意味着我们将在第 342 行 (SOURCE2) 上为每个要更新的元值调用函数 $this->update_or_delete_post_meta( $order,$value );。好的,这个函数看起来像这样:

/**
 * Update meta data in,or delete it from,the database.
 *
 * Avoids storing meta when it's either an empty string or empty array.
 * Other empty values such as numeric 0 and null should still be stored.
 * Data-stores can force meta to exist using `must_exist_meta_keys`.
 *
 * Note: WordPress `get_metadata` function returns an empty string when meta data does not exist.
 *
 * @param WC_Data $object The WP_Data object (WC_Coupon for coupons,etc).
 * @param string  $meta_key Meta key to update.
 * @param mixed   $meta_value Value to save.
 *
 * @since 3.6.0 Added to prevent empty meta being stored unless required.
 *
 * @return bool True if updated/deleted.
 */
protected function update_or_delete_post_meta( $object,$meta_value ) {
    if ( in_array( $meta_value,array( array(),'' ),true ) && ! in_array( $meta_key,$this->must_exist_meta_keys,true ) ) {
        $updated = delete_post_meta( $object->get_id(),$meta_key );
    } else {
        $updated = update_post_meta( $object->get_id(),$meta_value );
    }

    return (bool) $updated;
}

来源 3:https://woocommerce.github.io/code-reference/files/woocommerce-includes-data-stores-class-wc-data-store-wp.html#source-view.250

我们可以看到实际更新发生在第 254 行 (SOURCE3),当调用我认为是 WordPress 的原生 update_post_meta( $object->get_id(),$meta_value ); 函数时。

所以这是我的问题。如果第 254 行 (SOURCE3) 上的任何更新失败并且需要回滚整个订单创建,会发生什么情况?我们之前在 post 表的第 65 行 (SOURCE1) 中输入了一行。如果 post_meta 的更新之一失败,那么该行是否不需要删除,从而使我们的数据库顺序损坏?我无法弄清楚第 87 (SOURCE1) 行和 88 (SOURCE1) 行上的函数调用是否以任何方式验证订单创建的结果,以及它们是否作为某种 COMMIT/ROLLBACK 工作?甚至没有对第 86 (SOURCE1)、87 (SOURCE1)、88 (SOURCE1) 行的函数调用返回进行验证/错误处理。我们如何知道是否有任何失败?

此外,当读写会相互影响(脏/歪斜/幻象读/写)时,WordPress/Woocommerce 如何处理从数据库中的读/写,而不会发生锁定,因为有没有交易吗?

有人吗?

非常感谢!!

peak288 回答:Woocommerce/WordPress 和 ACID

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/5867.html

大家都在问