【发布时间】:2023-03-24 09:20:01
【问题描述】:
我有一个 MySQL 表,其中包含要发送的电子邮件。
在每次页面加载时,我都会检查是否有未发送的电子邮件,取其中几封并发送。
为了防止两个同时加载的页面发送同一封电子邮件,我正在考虑这样做:
$pdo = new PDO(...);
// Start blocking other page loads
$pdo->beginTransaction();
$stmt = $pdo->query("SELECT id, recipient, subject, body
FROM emails WHERE sent = 0 LIMIT 1 FOR UPDATE");
$mail = $stmt->fetch();
if(false !== $mail)
$pdo->exec("UPDATE emails SET sent = 1 WHERE id = $mail['id']");
// End blocking other page loads
$pdo->commit();
if(false !== $mail) {
// Send e-mail
}
但是如果在提交之后但在电子邮件成功发送之前中止执行怎么办?电子邮件将被视为已发送,但实际上并未发送。当然,我可以等到发送电子邮件后才提交,但这会导致更长的阻塞期。我通过 SMTP 发送电子邮件,发送一封电子邮件大约需要 10 秒。
您对如何解决这个问题有任何想法吗?一种选择可能是检测表是否被锁定,然后跳过这整个步骤。这可能吗?
【问题讨论】:
-
您是否因为无法在您的网络空间上使用 cronjobs 而在页面加载中检查这一点?
标签: php mysql email atomic race-condition