代码之家  ›  专栏  ›  技术社区  ›  AppleGrew

如果在MySQL中并发运行,我的update语句可以工作吗?

  •  0
  • AppleGrew  · 技术社区  · 6 年前

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

    我们有一个应用程序可以启动一个作业来批量发送许多消息。邮件传递状态将在以后分批接收,而不是按特定顺序接收。

    表格结构如下:

    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 设置为空。其值应从空更改为 sent 然后 delivered . 以下语句用于更新记录。

    当要设置的状态为- 交付

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

    当要设置的状态为- 发送

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

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

    上面的语句会确保mysql或mariadb中的这一点吗?

    3 回复  |  直到 6 年前
        1
  •  0
  •   Vladislav Vaintroub    6 年前

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

    • “sent”将覆盖空值,但不覆盖“delivered”
    • “delivered”将覆盖空值和“sent”

    这就是你想要的。在更新之前,请确保具有给定作业ID的消息存在:)

        2
  •  0
  •   Rick James diyism    6 年前
    Update message SET status = 'delivered', update_date = Now()
        WHERE job_id = :someId
          AND status = 'sent'    -- add this??
    

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

        3
  •  0
  •   Croco    6 年前
    Update message SET status = 'sent', update_date = Now()
    WHERE job_id = :someId
    AND status != 'delivered';