问题代码如下:
DB::table('records')->where('status','=', 1)->chunk(50, function ($records) {
if (empty($records)) {
return;
}
//执行更新
$records->each(function ($item, $key) {
DB::table('records')->where('id','=', $item['id'])->update(['status' => 2]);
});
});
问题分析
chunk方法解析的SQL形如:
SELECT * FROM records WHERE status = 1 OFFEST = {$offset} LIMIT {$limit}
以上代码解析的语句:
SELECT * FROM records WHERE status = 1 OFFEST = 0 LIMIT 50;
SELECT * FROM records WHERE status = 1 OFFEST = 50 LIMIT 50;
····
SELECT * FROM records WHERE status = 1 OFFEST = 50*n LIMIT 50;
如果查询条件一直在变化会导致OFFSET位移发生变化,导致错漏部分查询结果。
解决办法
$limit = 50;
while (true) {
$records = DB::table('records')->where('status','=', 1)->limit(50)->get();
//执行更新
$records->each(function ($item, $key) {
DB::table('records')->where('id','=', $item['id'])->update(['status' => 2]);
});
if(empty($records) || count($records) < $limit){
break;
}
}
总结
chunck 方法适用于记录查询场景,在更新记录是慎用