昨天在写脚本的时候,发现了一个问题,当我去分块去处理数据的时候,数据表的数据总是会出现缺失处理的情况。 在这里写个笔记 记录下这次的踩坑过程。 网上有好多地方能看到这个坑,但是都没有给出具体的解决方案。
Laravel中chunk方法分块处理数据的坑: Laravel中chunk方法分块处理数据
先说会引发这个问题的原因: 主要是因为数据表的查询与更新的where字段自同一张表,那么我们在更新数据的时候,就会因为chunk的分块机制,导致查询的数据是不全的。
这是chunk的分块机制源码:
public function chunk($count, callable $callback)
{
// 我理解的是类似于limit,offset 实现数据分页查询
$results = $this->forPage($page = 1, $count)->get();
while (count($results) > 0) {
// On each chunk result set, we will pass them to the callback and then let the
// developer take care of everything within the callback, which allows us to
// keep the memory low for spinning through large result sets for working.
// 如果用户回调中,更新的字段与查询的字段是一个条件,就会出现这样的问题
if (call_user_func($callback, $results) === false) {
return false;
}
$page++;
$results = $this->forPage($page, $count)->get();
}
return true;
}
那么如何解决这种问题呢? 我是这么处理的:
public function handle()
{
// 1.先去查询需要更新的数据量
$count = DB::table('table')
->where('status', '=', 0)
->count();
echo "需要推送的数量:$count\r\n";
while ($count) {
// 2.然后limit去查数据
$data= DB::table(self::OPEN_API_WUBA_TEST_CLUE)
->where('is_push', '=', self::IS_PUSH_FAILED)
->limit(100)
->get();
! empty($data) && $this->processData($data);
// 3.批次处理完数据,再去查询下 需要更新的数据,直到更新完毕退出循环
$count = DB::table('table')
->where('status', '=', 0)
->count();
echo "剩余推送的记录数:$count\r\n";
}
exit("数据全部推送完毕.\r\n");
}
private function processData($data)
{
// TODO(xiaoyi):处理数据业务逻辑
}