我想检查一下,这是迭代数据库中的行并在处理时删除它们的好方法吗?我第一次
但是,如果在“全部处理”步骤运行的同时添加了新行(来自外部),可能会出现问题。
// the limited for loop is to prevent an infinite loop
// assume the limit to be much higher than the expected
// number of rows to process
for ($i = 0; $i < $limit; $i++)
{
// get next mail in queue
$st = $db->prepare('
SELECT id, to, subject, message, attachment
FROM shop_mailqueue
LIMIT 0,1
');
$st->execute();
$mail = $st->fetch(PDO::FETCH_ASSOC);
// if no more mails in queue, stop
if ($mail === false) {
break;
}
// send queued mail
$mailer = new PHPMailer();
$mailer->AddAddress($mail['to']);
$mailer->SetFrom('info@xxx.nl', 'xxx.nl');
$mailer->Subject = $mail['subject'];
$mailer->Body = $mail['message'];
$mailer->AddAttachment($mail['attachment']);
$mailer->Send();
// remove mail from queue
$st = $db->prepare('
DELETE FROM shop_mailqueue WHERE id = :id
');
$st->bindValue('id', $mail['id']);
$st->execute();
}
答案 0 :(得分:2)
我认为你抓住所有,处理全部,删除所有方法都可以通过一个简单的改变:
delete from table
,而是做一个
delete from table where key in (<all keys retrieved>)
。您可以轻松构建&lt;检索到的所有密钥&gt;因为你先抓住一切。
这比执行现在要做的许多查询要好(很多)。
答案 1 :(得分:1)
首先,任何时候你说“迭代数据库中的行”,你最好谈论每一行发生的一些非常复杂的操作。否则,你可以而且应该一起思考!
看起来你在发送所有电子邮件后将所有内容都放在邮件队列中并转储表。现在,我应该注意到你的limit 0,1
有点令人不安,因为你没有order by
。没有数据库以可靠的顺序存储东西(并且有充分的理由 - 它必须不断地移动以优化它们)。所以,更好的代码是:
// get next mail in queue
$st = $db->prepare('
SELECT id, to, subject, message, attachment
FROM shop_mailqueue
ORDER BY id ASC
LIMIT 0, ' . $limit);
$st->execute();
$lastid = 0;
while ($mail = $st->fetch(PDO::FETCH_ASSOC))
{
// send queued mail
$mailer = new PHPMailer();
$mailer->AddAddress($mail['to']);
$mailer->SetFrom('info@xxx.nl', 'xxx.nl');
$mailer->Subject = $mail['subject'];
$mailer->Body = $mail['message'];
$mailer->AddAttachment($mail['attachment']);
$mailer->Send();
$lastid = $mail['id'];
}
// remove mail from queue
$st = $db->prepare('DELETE FROM shop_mailqueue WHERE id <= ' . $lastid);
$st->execute();
这样,你只需要对数据库进行两次(计数'em!)查询,这比每次拉回一行 更优化。
现在,如果整个$limit
交易是不必要的,并且您真的想要撤回队列中的所有行,然后只是将队列转储出来,请将delete
语句更改为:< / p>
TRUNCATE TABLE shop_mailqueue
请参阅,truncate
不受事务逻辑的约束,只需擦除表格,没有问题。因此,它非常快(无论表大小如何,以毫秒为单位)。 delete
只是没有那种速度。请记住truncate
是一个核选项 - 一旦你truncate
,它就消失了。
答案 2 :(得分:0)
您可以在处理过程中锁定表格
答案 3 :(得分:0)
我认为你做得很好。您获取所有内容,处理它们并仅删除您处理的内容。我也不会在你的过程中锁定表格,因为你会阻止那些创建记录的人。
如果您遇到的唯一问题是处理在发送现有电子邮件时可能已创建的电子邮件,那么您可以在所有程序之上创建一个while
循环以便始终运行当有新记录时。
此外,为什么要获得LIMIT 0,1
($limit
)次,如果您只需修改查询以在一个查询LIMIT 0,$limit
中获取最多$ limit项。