问题描述
据我所知,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 );
}
}
在第 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 );
}
好的,在第 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;
}
我们可以看到实际更新发生在第 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 如何处理从数据库中的读/写,而不会发生锁定,因为有没有交易吗?
有人吗?
非常感谢!!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)