如何使用PHP执行MySQL行锁并删除行?

时间:2015-07-07 20:44:40

标签: mysql locking innodb

LAMP堆栈 - 所以代码是PHP

我有一个innodb表 - 名为queueTable

有一个cron作业每15分钟运行一次,查询数据库以确定是否需要将任何记录放入queueTable。有时没有记录添加到queueTable,有时可能会有超过1,000条记录添加到queueTable。

需要发生的是需要读取queueTable中的每一行,需要执行一个进程,然后需要删除该行。

目前,我有两个守护进程作业,除了每5秒查询一次queueTable之外什么都不做。

一个作业读取所有奇数行记录,另一个读取所有偶数行记录。为了快速完成所有处理,有两个工作(两个工作优于一个)。

我希望在queueTable中为所有人创建20个守护进程 - 从而将行中的一行时间减少到最小值。

将其视为一个邮件队列(它不是,但是有一个好的例子可以工作)。

我需要尽快清空队列。

我可以执行事务并锁定行,但这并不妨碍另一个守护程序尝试锁定同一行。如果一个守护进程试图读取一个锁定的行 - 它将等待它会发生什么。但锁定该行的守护进程将删除它。不确定第二个守护进程在那时做了什么?

完成我想要做的事情的最佳方法是什么?

我希望这是有道理的。

谢谢!

BTW - 我尝试过pthreads - 并发现它在吞吐量方面确实没什么帮助。 IE浏览器。读取记录并在它获得下一条记录之前处理它的过程 - 如果我在多线程模式下执行(IE每个进程都是新线程),清空队列的时间与执行相同每一行一个。至少在我的测试中是这样的。

1 个答案:

答案 0 :(得分:0)

我在MySQL中实现队列的口头禅:“不要排队,只要这样做!”

使用PHP进行多处理并不容易实现。 Perl(也是Lamp的一部分)要好得多。此外,由于这是一项后台任务,请将Web服务器和浏览器(Apache + IE)保持在图片之外;它们是很多开销。

处理一个“项目”需要多长时间?如果只需几秒钟,那么BEGIN; SELECT one item FOR UPDATE; process it; COMMIT;

如果需要更长的时间,请不要将BEGIN...COMMIT放在一切;而是做类似的事情:

SET autocommit=1

  1. $id = SELECT id ... WHERE process_id IS NULL ORDER BY ... LIMIT 1;(或者你可以抓住10并且有一个步骤2..5的内循环。)
  2. UPDATE ... SET process_id = $pid WHERE id = $id AND process_id IS NULL;并检查它是否有效。请注意,SELECTUPDATE故意不在交易中;这是为了尽量减少干扰。但是,如果没有事务处理,另一个线程就会抓住它。如果是这样,rows_affected将为0;回到第1步。
  3. 处理项目
  4. UPDATE (or DELETE) ... SET process_id = NULL WHERE id = $item; - 释放锁定
  5. sleep(1) - 稍微延迟 - 避免人为地淹没系统。这可能需要调整。
  6. 返回第1步。
  7. 你可以有任意数量的线程。