如果在MySQL中同时运行,我的UPDATE语句可以工作吗?

时间:2018-11-20 17:49:12

标签: mysql mariadb concurrentmodification

我看到了许多类似的问题,但是我仍然不确定我是否正确。

我们有一个应用程序,它可以启动工作以大量发送许多消息。邮件的发送状态以后将分批接收,并且没有特定的顺序。

表结构类似于:-

CREATE TABLE `message` (
  `pk` char(32) NOT NULL DEFAULT '',
  `job_id` varchar(40) DEFAULT NULL,
  `status` varchar(40) DEFAULT NULL,
  `update_date` datetime DEFAULT NULL,
  PRIMARY KEY (`pk`),
  KEY `job_id` (`job_id`),
  KEY `status` (`status`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

最初创建的记录是将status设置为null。预期其值将从null更改为sent,然后更改为delivered。以下语句用于更新记录。

要设置的状态为-delivered

Update message SET status = 'delivered', update_date = Now()
    WHERE job_id = :someId

要设置的状态为-sent

Update message SET status = 'sent', update_date = Now()
    WHERE job_id = :someId AND status IS NULL

问题是,可能有两个线程同时尝试将同一记录的status设置为“已发送”和“已交付”。在这种情况下,“已交付”是最终状态,因此我们希望最终获得胜利。

以上语句将确保在MySql或MariaDB中做到这一点吗?

3 个答案:

答案 0 :(得分:0)

Update message SET status = 'delivered', update_date = Now()
    WHERE job_id = :someId
      AND status = 'sent'    -- add this??

(MySQL和MariaDB在这方面应该没有区别。)

答案 1 :(得分:0)

Update message SET status = 'sent', update_date = Now()
WHERE job_id = :someId
AND status != 'delivered';

答案 2 :(得分:0)

是的,在MySQL和MariaDB(可能还有任何SQL数据库)中。 对同一行的更新是原子的。

  • “已发送”将覆盖NULL,但不会“传递”
  • “已交付”将覆盖NULL并“发送”

这就是您想要的。只需确保存在具有给定job_id的消息,然后再进行更新即可:)