MySQL环境下WooCommerce自定义客户表偶发更新异常问题咨询
预制餐客户数据表偶发同步失败问题
因无法提供最小可复现示例,在此向各位致歉。
我方为周度预制餐配送服务商,需通过多维度统计订单量,以下为相关数据表的结构说明:

我在业务中会用到表中高亮标注的字段,例如通过规则 last_order_w - prev_order_w > 4 判断客户距上次下单是否超过1个月,为配送司机提供客户复购状态提示。
近期观测到近3周内约5%的概率该数据表未正常完成更新,问题无法稳定复现,也无对应错误日志,难以定位问题诱因。
负责触发数据更新的脚本代码如下:
<?php // 拉取上次同步后产生的所有新订单ID并遍历处理 $newOrders = array_map('reset', $dbh->query("select id from wp_posts where id > (select max(synced) from fitaf_weeks) and post_type='shop_order' and post_status='wc-processing'")->fetchAll(PDO::FETCH_NUM)); foreach($newOrders as $no){ // 查询当前订单的所有元数据 $newMetas = array_map('reset', $dbh->query("select meta_key,meta_value from wp_postmeta where post_id=$no")->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE)); // 校验当前订单关联的客户是否已存在于客户表 $exist = $dbh->query("select * from fitaf_customers where id=" . $newMetas['_customer_user'])->fetch(); // 客户不存在时,组装新客户的入库字段 $noExist = [ $newMetas['_customer_user'], $newMetas['_shipping_first_name'], $newMetas['_shipping_last_name'], $newMetas['_shipping_address_1'], (strlen($newMetas['_shipping_address_2']) == 0 ? NULL : $newMetas['_shipping_address_2']), $newMetas['_shipping_city'], $newMetas['_shipping_state'], $newMetas['_shipping_postcode'], $phone, $newMetas['_billing_email'], 1, 1, $no, $newMetas['_paid_date'], $week[3], $newMetas['_order_total'] ]; if($exist){ // 客户存在时,查询客户表原有历史订单数据 $oldO = $dbh->query("select last_order_id,last_order,last_order_w,lo,num_orders from fitaf_customers where id=" . $newMetas['_customer_user'])->fetch(PDO::FETCH_GROUP|PDO::FETCH_ASSOC|PDO::FETCH_UNIQUE); // 组装更新字段:保留最新配送地址,计算订单数、消费总额等指标 $exists = [ $phone, $newMetas['_shipping_first_name'], $newMetas['_shipping_last_name'], $newMetas['_shipping_postcode'], $newMetas['_shipping_address_1'], (strlen($newMetas['_shipping_address_2']) == 0 ? NULL : $newMetas['_shipping_address_2']), $newMetas['_shipping_city'], $newMetas['_shipping_state'], $newMetas['_paid_date'], $no, $week[3], $oldO['last_order'], $oldO['last_order_id'], $oldO['last_order_w'], ($oldO['num_orders'] + 1), ($oldO['lo'] + $newMetas['_order_total']), $newMetas['_customer_user'] ]; } // 客户不存在则执行插入操作 if(!$exist){ $dbh->prepare("insert into fitaf_customers(id,fname,lname,addr1,addr2,city,state,zip,phone,email,num_orders,num_weeks,last_order_id,last_order,last_order_w,lo) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")->execute($noExist); } else { // 客户存在则执行更新操作 $dbh->prepare("update fitaf_customers set phone=?,fname=?,lname=?,zip=?,addr1=?,addr2=?,city=?,`state`=?,last_order=?,last_order_id=?,last_order_w=?,prev_order=?,prev_order_id=?,prev_order_w=?,num_orders=?,lo=? where id=?")->execute($exists); } } // 脚本结束后,查询所有shop_order类型订单的最大ID,更新同步标记 $lastPlaced = $dbh->query('select max(id) from wp_posts where post_type="shop_order"')->fetch()[0]; $updateSync = $dbh->query("update fitaf_weeks set synced=$lastPlaced order by id desc limit 1"); ?>
目前未检索到相关错误日志,在梳理本次问题的代码逻辑时,发现了一个潜在缺陷:原脚本完成同步后,会直接查询wp_posts中所有shop_order类型的最大ID来更新fitaf_weeks表的synced同步标记,而非使用本次脚本查询到的新订单列表$newOrders的最大ID。
理论上,该cron任务每5分钟运行一次,且该同步逻辑运行时长从未超过3秒,不应出现任务运行重叠的问题,但仍担心该问题是导致异常的诱因。
目前已将同步标记的更新逻辑修改为取$newOrders的最大ID,期望能解决该问题,但仍希望咨询这类低概率偶发数据更新失败的可能根因。
内容的提问来源于stack exchange,提问作者macheteYeti
相关产品推荐
相关产品推荐

