PHP 循环执行异步操作(数据库操作)时,发现执行了两次问题解决
在做一个数据维护工作的 php 脚本时,从插入数据库的记录中发现,数据记录被插入了两次。
通过加入 Log 日志标记发现,问题源头在 foreach 循环执行上数据库操作上。查看循环对象,并没有重复记录,所以是 foreach 方法体本身执行了两次,这是我不能理解的。猜测与循环执行的数据库异步操作有关。
以下为循环异步操作的代码示例:
$orders = Orders::where('money', '>', 0)->get();
foreach ($orders as $order) {
if ($order->id == 1111) {
Log::info('['.date('H:i:s').'] [order_id] 1111 executing...');
}
$this->customer_orders->handleProfit($order, $order->money);
}
$customer_orders
是自动注入的 repository
类,handleProfit
则主要处理数据维护的操作。
日志内容:
[2021-09-29 10:41:37] production.INFO: [10:41:37] [order_id] 1111 executing...
[2021-09-29 10:41:37] production.INFO: [10:41:37] [order_id] 1111 executing...
可以看到两次执行时间几乎为同一时间,js 在处理循环内异步操作时也会发生相同的情况。
我的猜想:
在循环中某一异步操作(需要执行很长时间时),循环体会自动执行下一次操作。等到异步操作返回时,循环重新执行的地方是方法体首行。这就导致了循环体被重复执行了一次,包括异步操作本身。
解决方法
在 handleProfit
添加 return
返回语句,使得循环体需要等待异步操作结束再去执行下一次循环。异步变同步,这样就可以了。