【问题标题】:Are single queries that update multiple rows in MySQL Atomic?是更新 MySQL Atomic 中多行的单个查询吗?
【发布时间】:2020-05-28 13:57:11
【问题描述】:

我在 SpringJPA 中执行的 MySQL InnoDb 表中有一个查询,该查询更新了多行。我想确保查询完成并且它将更新的行不能被任何其他进程更新。这是在多 CPU 环境中,所以我必须在数据库级别进行锁定。

我首先使用如下查询选择行:

select * from tablea where status = 1;

假设这会返回 3 行 - 主 ID 为 1,2,3

我想阻止并发更新,我做了这个更新:

update tablea set status=2 where status=1 and primaryIds in (1,2,3);

我要完成的是检查我要更新的所有行在状态中是否仍然具有原始值,并且在我下面没有更新。然后我获取更新的行数并将其与主 ID 数 (3) 进行比较,以了解我的查询是否已更新所有行。我的问题是这个查询原子 - 它会返回 3 还是 0。如果行数更多,它将产生允许另一个线程,尝试执行相同的更新来更新某些行。我已经用一行测试了它,它工作正常。

【问题讨论】:

  • 原子性与返回 3 或 0 作为查询的受影响行数不同!原子性意味着它将完全运行或根本不更改任何内容(例如,如果它在第 2 行遇到错误,它将撤消对第 1 行的更改)。这并不意味着数据不能在选择和更新之间改变。如果您确实想确定这一点,请更准确/改写它,尤其是您的标题,因为您(可能)实际上并不想知道单个查询是否是原子的。
  • 谢谢你,但我想你理解我的问题。也就是说,它会保证所有三行都更新还是没有更新。是否有可能会更新 2 行而不会更新 1 行。
  • 是的(如果有人在您的选择和更新之间更新了表格)。但我的编辑建议是确保不仅我,而且其他所有人都不会忽视“它会返回 3 还是 0”这 7 个词,这使得这是一个完全不同的问题(尤其是与您的标题不匹配)。包括在您的标题中有问题的未来读者,并通过搜索引擎找到这个问题,并会看到一个“不”的答案,并认为它回答了标题中的问题。如果有人遇到了你的实际问题,没有人会仅仅通过这 7 个字就能找到它。

标签: mysql atomic


【解决方案1】:

是的,他们是。假设您启用了自动提交(这是您尚未启动事务时的默认设置),InnoDB 将自动在每个查询周围放置一个事务,这使其具有原子性。它实际上相当于:

START TRANSACTION;
update tablea set status=2 where status=1 and primaryIds in (1,2,3);
COMMIT;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多