LAMP 堆栈 - 所以代码是 PHP
我有一个 innodb 表 - 称为queueTable
有一个每 15 分钟运行一次的 cron 作业,它查询数据库以确定是否需要将任何记录放入队列表中。有时没有记录添加到queueTable,有时可能有超过1000条记录添加到queueTable。
需要发生的是需要读取queueTable中的每一行,需要执行一个过程,然后需要删除该行。
目前,我有两个守护进程作业,除了每 5 秒查询一次队列表之外什么也不做。
一个作业读取所有奇数行记录,另一个作业读取所有偶数行记录。为了快速完成所有处理,有两个作业(两个作业比一个好)。
我想创建大约 20 个守护进程来全部进入队列表 - 从而将行在队列表中的生存时间降至最低。
将其视为一个邮件队列(它不是一个有效的示例)。
我需要尽快清空队列。
我可以执行事务并锁定该行,但这并不能阻止另一个守护程序尝试锁定同一行。如果守护程序尝试读取锁定的行,将会发生什么 - 它会等待它。但是锁定该行的守护进程将删除它。不确定第二个守护进程此时会做什么?
完成我想做的事情的最佳方法是什么?
我希望这是有道理的。
谢谢!
顺便说一句 - 我尝试过 pthreads - 发现它在吞吐量方面确实没有多大帮助。 IE。读取一条记录并在获取下一条记录之前对其进行处理的进程 - 如果我在多线程模式下执行此操作(即每个进程都是一个新线程),则清空队列的时间与执行每一行的时间相同一次。至少在我的测试中是这样。
最佳答案
我在 MySQL 中实现队列的口头禅:“不要排队,直接去做!”
使用 PHP 进行多重处理并不是那么容易实现的。 Perl(也是 Lamp 的一部分)要好得多。此外,由于这是一项后台任务,因此请将 Web 服务器和浏览器 (Apache + IE) 排除在外;它们的开销很大。
处理一件“元素”需要多长时间?如果只需要几秒钟,那么BEGIN; SELECT one item FOR UPDATE; process it; COMMIT;
如果需要的时间比这更长,请勿输入 BEGIN...COMMIT
围绕一切;相反,做类似的事情:
SET autocommit=1
-
$id = SELECT id ... WHERE process_id IS NULL ORDER BY ... LIMIT 1;
(或者您可以获取 10 个并进行步骤 2..5 的内部循环。) -
UPDATE ... SET process_id = $pid WHERE id = $id AND process_id IS NULL;
并检查它是否有效。请注意SELECT
和UPDATE
故意不参与交易;这是为了尽量减少干扰。然而,如果没有事务,另一个线程很有可能会捕获它。如果是这样,rows_affected 将为 0;返回步骤 1。 - 处理该项目
-
UPDATE (or DELETE) ... SET process_id = NULL WHERE id = $item;
-- 释放锁 -
sleep(1)
——延迟一点——以避免人为地淹没系统。这可能需要调整。 - 返回第 1 步。
您可以让任意数量的线程执行此操作。
关于mysql - 如何使用 PHP 执行 MySQL 行锁定和删除行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31278918/