首页 > 解决方案 > 如果在 MySQL 中同时运行,我的 UPDATE 语句可以工作吗?

问题描述

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

我们有一个应用程序,它启动一个工作来大量发送许多消息。消息传递状态稍后分批接收,没有特定顺序。

表结构如下:-

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 中确保这一点吗?

标签: mysqlmariadbconcurrentmodification

解决方案


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

  • 'sent' 会覆盖 NULL,但不会 'delivered'
  • 'delivered' 将覆盖 NULL 和 'sent'

这就是你想要的。只需确保在更新之前存在具有给定 job_id 的消息 :)


推荐阅读