Mặc dù tôi vẫn nghi ngờ rằng các giao dịch và / hoặc chèn hàng loạt là giải pháp khả thi cho vấn đề sử dụng tài nguyên của bạn, nhưng chúng vẫn là giải pháp tốt hơn so với việc chuẩn bị các báo cáo khổng lồ như Dave đã đề xuất.
Hãy thử những điều này và xem chúng có giúp ích gì không.
Phần sau giả định rằng chế độ xử lý lỗi của PDO được thiết lập để đưa ra các ngoại lệ. Ví dụ:$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Nếu vì lý do nào đó, bạn không thể sử dụng chế độ Ngoại lệ thì bạn sẽ cần kiểm tra kết quả trả về của execute()
mỗi lần và ném Ngoại lệ của riêng bạn.
Giao dịch đơn lẻ:
$sql = $db->prepare("INSERT INTO players (name, level, vocation, world, month, today, online) VALUES (:name, :level, :vocation, :world, :time, :time, :online) ON DUPLICATE KEY UPDATE level = :level, vocation = :vocation, world = :world, month = month + :time, today = today + :time, online = :online");
$db->beginTransaction();
try {
foreach ($players as $player) {
$sql->execute([
":name" => $player->name,
":level" => $player->level,
":vocation" => $player->vocation,
":world" => $player->world,
":time" => $player->time,
":online" => $player->online
]);
}
$db->commit();
} catch( PDOException $e ) {
$db->rollBack();
// at this point you would want to implement some sort of error handling
// or potentially re-throw the exception to be handled at a higher layer
}
Giao dịch theo đợt:
$batch_size = 1000;
for( $i=0,$c=count($players); $i<$c; $i+=$batch_size ) {
$db->beginTransaction();
try {
for( $k=$i; $k<$c && $k<$i+$batch_size; $k++ ) {
$player = $players[$k];
$sql->execute([
":name" => $player->name,
":level" => $player->level,
":vocation" => $player->vocation,
":world" => $player->world,
":time" => $player->time,
":online" => $player->online
]);
}
} catch( PDOException $e ) {
$db->rollBack();
// at this point you would want to implement some sort of error handling
// or potentially re-throw the exception to be handled at a higher layer
break;
}
$db->commit();
}