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

问题描述 投票:-1回答:1

我有一个PHP脚本,该脚本每天运行,遍历所有用户以向他们发送文本并更新其状态。基本上就像这样...((伪代码)

$sql="SELECT UserPhone from users WHERE Status='LOW'";
while($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) {
   // loop through and send texts
}
// then update status
$sql="UPDATE users SET Status='MED'";

我可以检测文本是否已成功发送,如果文本成功,我只想更新用户的状态。我的第一个直觉是将UPDATE移到while循环中,并分别更新每个用户的行,类似这样,再次使用伪代码:

while($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) {
    $sent=sendText($phone);
    if($sent) {
        $sql=UPDATE users SET Status='MED' WHERE UserPhone=$phone";
    }
}

这让我感到笨拙,我猜这对性能不利。感觉我应该能够存储/记住发送了哪些文本,并使用单个UPDATE(或至少不需要每行都不需要新的UPDATE的更新)来更新所有这些用户。

我知道只有足够多的MySQL可以用它做一些愚蠢的事情。有一个更好的方法吗?

php mysql mysqli
1个回答
0
投票

您可以执行以下操作:

$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);

但是这是一个风险。如果PHP脚本在途中被中断怎么办?例如,在while循环期间,也许其中一个文本发送会导致致命错误,并且脚本退出,从而丢失了迄今为止积累的关于成功文本的信息。

我在SchoolMessenger.com工作了两年。我们每天发送多达900万条文本(自从我辞职以来,现在可能更高)。

这是完成任务的伪代码(我们的服务是用Java而不是PHP编写的:

for each user who should be sent a text {
  INSERT INTO Tasks SET UserPhone = ?, Message = ?, Status = 'TODO'
}

然后,每个用户每个文本有一行要发送。还有另一个程序监视此任务表,以查找状态为“ 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'
}

这似乎很笨拙,但是许多类似这样的系统旨在记住它们崩溃时离开的地方。一次将结果保存到数据库会有帮助,因为一旦程序启动,它就可以查看已发送的文本,并避免重新发送任何文本(因为小学生的父母不希望收到相同的消息重复)。

© www.soinside.com 2019 - 2024. All rights reserved.