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

如何使用PHP执行MySQL行锁定和删除行?,mysql,locking,innodb,Mysql,Locking,Innodb,LAMP堆栈-因此代码是PHP 我有一个名为queueTable的innodb表 有一个cron作业每15分钟运行一次,查询数据库以确定是否需要将任何记录放入queueTable。有时并没有记录添加到queueTable,有时可能会有超过1000条记录添加到queueTable 需要做的是读取queueTable中的每一行,执行一个进程,然后删除该行 目前,我有两个守护进程作业,每5秒只查询queueTable一次 一个作业读取所有奇数行记录,另一个读取所有偶数行记录。为了快速完成所有处理,有两

LAMP堆栈-因此代码是PHP

我有一个名为queueTable的innodb表

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

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

目前,我有两个守护进程作业,每5秒只查询queueTable一次

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

我想创建大约20个守护进程,所有守护进程都在queueTable中运行,从而将一行在queueTable中的生存时间缩短到最小

可以将其视为一个邮件队列(这不是一个很好的例子)

我需要尽快清空队列

我可以执行一个事务并锁定该行,但这并不阻止另一个守护进程尝试锁定同一行。如果一个守护进程试图读取一个锁定的行,它将等待它。但是锁定该行的守护进程将删除它。不确定第二个守护进程在这一点上做了什么

要完成我想做的事情,最好的方法是什么

我希望这是有道理的

谢谢


顺便说一句,我尝试过pthreads,但发现它在吞吐量方面并没有多大帮助。即,读取一条记录并在其成为下一条记录之前对其进行处理的进程-如果我以多线程模式(即每个进程都是一个新线程)执行此操作,则清空队列的时间与一次一行地执行相同。至少在我的测试中是这样的。

我在MySQL中实现队列的咒语:“不要对它排队,只要做就行了!”

用PHP实现多处理并不是那么容易。Perl(也是Lamp的一部分)要好得多。此外,由于这是一项后台任务,因此不要使用web服务器和浏览器(Apache+IE);他们的开销很大

处理一个“项目”需要多长时间?如果只需要几秒钟,则
开始;选择一项进行更新;处理它;承诺

如果需要更长的时间,不要把
BEGIN…COMMIT
放在所有东西周围;相反,你可以这样做:

设置自动提交=1

  • $id=选择id。。。其中,进程\u id为NULL ORDER BY。。。限值1(或者,您可以抓取10个步骤,并进行步骤2..5的内部循环。)
  • 更新。。。设置进程id=$pid,其中id=$id,进程id为空
    并检查它是否有效。请注意,
    SELECT
    UPDATE
    故意不在事务中;这是为了尽量减少干扰。然而,如果没有事务,另一个线程将抓住它的可能性很小。如果是,受影响的行将为0;返回到步骤1
  • 处理项目
  • 更新(或删除)。。。设置进程\u id=NULL,其中id=$item--释放锁
  • 睡眠(1)
    ——稍微延迟一点——以避免人为地淹没系统。这可能需要调整
  • 返回到步骤1

  • 您可以让任意数量的线程执行此操作。

    锁是原子的。要么成功,要么失败。不能让两个不同的客户端锁定同一条记录,因为只有一个客户端可以成功。数据库表是事务性的,如果您的密钥定义正确,那么简单地运行一个查询并执行一个或多个步骤应该比尝试创建一个php线程解决方案更快,因为php是无状态的。你为什么这么做?或者你为什么认为这是解决问题的好方法?你甚至可以在这里使用存储过程来解释我为什么要这么做。。。这是一个时间问题。我们正在处理的信息需要在一分钟内处理-无论有多少记录。现在有两个守护进程作业,当队列表中有几千条记录时,守护进程在大约4分钟内处理这些记录。信息对时间相当关键,因此在一分钟内处理数据是一项重要的要求。真正的解决方案是使用RabbitMQ或其他队列技术。它有php版本,但下面是一个示例:。这应该对你有好处。正如我在前面的评论中所述,唯一更好的解决方案是存储过程,它在向表中添加行时激活。理想情况下,使用队列,您可以让它创建单个工人,因为数据可用,而不是作为一个巨大的“批次”。在理想情况下,可能会工作,但创建这些记录的作业会成批进行。。。创建大约4000条记录大约需要15秒。我将检查rabitMq,然后事务锁定(来自多个线程)可以工作吗?因此,所有记录都将被处理(并在提交流程/事务时删除),并且任何行都不可能被处理多次?步骤1得到一个暂定项。第2步是棘手的一步:它以原子方式抓取它或得到零行影响。第4步从考虑中删除到行。我更新了第2步和第4步。关于如何实现这一点,有很多变体,但这是一般的想法。我设计它的目的是几乎没有锁。步骤1可能需要一个更好的索引来最小化它的时间。步骤2和4(假设
    主键(id)
    )的锁定时间非常短。通过不使用事务,而是使用自动提交,每个语句都是独立的。(步骤3可能有事务;但那是另一回事。)步骤1是最大的开销;关注它。实际上,开始,选择更新,处理,删除,提交似乎都很有效。我有两份工作在一个8500行的测试表上做同样的事情。第一次迭代,而不是o