如何防止存储过程同时运行两次?

问题描述

我使用 aurora DB(即 MysqL 版本 5.6.10)作为队列,并且我使用存储过程从表中批量提取记录。 sproc 使用以下步骤...

  1. 选择下一批数据放入临时表
  2. 将临时表中记录的ID写入日志表
  3. 输出记录

一旦一条记录被添加到日志中,sproc 下次调用时不会再次选择它,所以多个服务器可以调用这个 sproc,并且都处理队列中的批量数据而不会互相踩踏.

sproc 在几分之一秒内运行,但我的公司现在正在自动启动服务器,这些克隆的服务器在 完全 调用 sproc,结果是一样的记录被选择两次

有什么办法可以让这个 sproc 一次只能调用一次?理想情况下,任何额外的调用都应该等到第一个调用完成后才能运行

不幸的是,我几乎没有使用 MysqL 的经验,所以我不确定从哪里开始。如果有人能指出我正确的方向,我将不胜感激

解决方法

这是 MySQL table locking 的工作。尝试这样的事情。 (您没有向我们展示您的查询,因此这里有很多猜测。)

SET autocommit = 0;
LOCK TABLES logtable WRITE;
CREATE TEMPORARY TABLE temptable AS 
        SELECT whatever FROM whatevertable FOR UPDATE;
INSERT INTO logtable (id) 
          SELECT id FROM temptable;
COMMIT;
UNLOCK TABLES;

如果多个连接尝试同时运行此序列,则一个连接将等待另一个连接 UNLOCK TABLES; 继续。你说你的 SP 很快,所以可能没有人会注意到短暂的等待。

专业提示:当您在许多服务器上运行相同的定时代码时,最好在运行作业之前进行短暂的随机延迟。这样共享资源(比如你的 MySQL 数据库)就不会受到大量精确同步的请求的影响。