Php MySQL-基于文本发送/失败更新多行的最佳方式

Php MySQL-基于文本发送/失败更新多行的最佳方式,php,mysql,mysqli,Php,Mysql,Mysqli,我有一个PHP脚本,每天运行,循环通过所有用户向他们发送文本,并更新他们的状态。基本上是这样的…(伪代码) 我可以检测文本是否成功发送,我只想在文本成功时更新用户的状态。我的第一反应是将更新移动到while循环中,并分别更新每个用户的行,类似这样的伪代码: while($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) { $sent=sendText($phone); if($sent) { $sql=UPDATE

我有一个PHP脚本,每天运行,循环通过所有用户向他们发送文本,并更新他们的状态。基本上是这样的…(伪代码)

我可以检测文本是否成功发送,我只想在文本成功时更新用户的状态。我的第一反应是将更新移动到while循环中,并分别更新每个用户的行,类似这样的伪代码:

while($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) {
    $sent=sendText($phone);
    if($sent) {
        $sql=UPDATE users SET Status='MED' WHERE UserPhone=$phone";
    }
}
这对我来说很笨重,我猜这对性能不好。感觉上,我应该能够存储/记住发送的文本,并通过一次更新(或者至少是不需要每行更新的内容)更新所有这些用户


我知道的MySQL足以用它来做蠢事。有更好的方法吗

您可以这样做:

$sql="SELECT UserPhone from users WHERE Status='LOW'";
$successes = []
while($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) {
   // loop through and send texts, set $ok to the success/fail
   if ($ok) {
      $successes[] = $row['UserPhone']
   }
}
// then update status
$placeholders = implode(",", array_fill(0, count($successes), "?");
$sql="UPDATE users SET Status='MED' WHERE UserPhone IN ($placeholders)";
$stmt = mysqli_prepare($sql);
$stmt->bind_param(str_repeat("s", count($successes)), ...$successes);
$stmt->execute();
但这是一种风险。如果PHP脚本中途中断怎么办?例如,在while循环期间,可能有一个文本发送导致了致命错误,脚本退出,丢失了迄今为止积累的关于哪些文本成功的信息

我在SchoolMessenger.com工作了两年。我们每天发送多达900万条短信(自从我离职后,这个数字可能会更高)

下面是我们如何完成任务的伪代码(我们的服务是用Java编写的,不是PHP):

然后,每个用户每个文本有一行要发送。有另一个程序监视此任务表,查找任何状态为“TODO”的任务。当发现存在某些行时:

for each row in Tasks that is 'TODO' {
  Send the text message
  Check success
  Update the status on that one row to 'Success' or 'Fail'
}

这看起来很笨重,但是很多这样的系统都是为了记住它们在崩溃时从哪里中断的。将结果一步一步地保存到数据库中会有所帮助,因为一旦程序启动,它可以看到哪些文本已经发送,并避免重新发送任何文本(因为学童的家长不希望重复接收相同的消息).

我不明白选择的意义。您可以通过在数组中记住电话号码,然后在子句末尾使用
调用单个更新来避免多次单次更新。也许这有助于:
for each user who should be sent a text {
  INSERT INTO Tasks SET UserPhone = ?, Message = ?, Status = 'TODO'
}
for each row in Tasks that is 'TODO' {
  Send the text message
  Check success
  Update the status on that one row to 'Success' or 'Fail'
}