【发布时间】: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 个字就能找到它。