mysql - 竞态条件下的 INSERT-SELECT 和 UPDATE
问题描述
#1:如果我跑步
INSERT INTO foo SELECT MAX(X) FROM bar;
X
我可以确定我刚刚从表中插入了该列的最大值bar
吗?在零件完成后但在完成之前没有其他会话设法操纵bar
表格?SELECT
INSERT
#2:如果我跑步
UPDATE foo SET x = 0 WHERE y = 100;
当时钟到达 00:00 并且查询需要 2 分钟时,我可以确定y = 100
在 00:00 的所有行都已更新吗?在我的查询完成之前没有其他会话设法更改y = 100
?y = 80
#3:这与#2有关。如果在 00:01 另一个会话UPDATE
通过更改y = 99
为s 对某行执行 s y = 100
,我之前的查询是否会尝试UPDATE
该行?
解决方案
如果您不使用显式事务,则每个查询本身都会被视为一个事务。因此,结合INSERT
并SELECT
喜欢您的#1 的查询可能取决于一致性。它大致相当于:
START TRANSACTION;
SET @max = (SELECT MAX(x) FROM bar);
INSERT INTO foo VALUES (@max);
COMMIT;
但是,事务不会在事务开始时创建整个数据库的快照。InnoDB 使用每条记录锁定。因此,在 #2 和 #3 中,如果您y
在会话 B 执行您显示的查询时更新会话 A,则 B 更新的记录可能包括也可能不包括由 A 修改的记录,具体取决于这些特定更改的相对顺序。另一方面,MyISAM 使用表级锁,所以这应该是不可能的;无论哪个查询先开始,都会锁定foo
表,而另一个查询将等待它完成,然后再开始扫描表。
推荐阅读
- java - 如何解决 java.lang.NullPointerException:无法调用“javax.mail.internet.MimeMessage.getSentDate()”,因为“mimeMessage”为空]
- mocking - Mockito 测试失败,类型为“Null”不是“Future”类型的子类型
' - python-3.x - 使用 pyinstaller 和烧瓶应用程序打开浏览器并检测浏览器选项卡何时关闭?
- spring - 搭建Spring boot comman核心库模块
- javascript - Json 解析 url prestashop webservice
- excel - 将数据从数据透视表复制到另一个
- android-ndk - 为什么我在执行使用 Android NDK 构建的程序时收到未定义符号错误?
- ios - 与 mapView.animate 一起使用时 GMSCameraUpdate 有时不起作用
- ethereum - 为什么以及何时调用 setApprovalForAll?
- python - Python Beautiful Soup:获取类元素文本的问题