#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分钟时,我是否可以确定所有在00:00带有y = 100
的行都已更新?在我的查询完成之前,没有其他会话设法将y = 100
更改为y = 80
吗?
#3:与#2有关。如果在00:01,另一个会话通过将UPDATE
更改为y = 99
而将y = 100
移至一行,那么我先前的查询是否尝试UPDATE
移至该行?
答案 0 :(得分:1)
如果您不使用显式事务,则每个查询本身都会被视为事务。因此,像您的#1一样结合了INSERT
和SELECT
的查询可能取决于一致性。大致相当于:
START TRANSACTION;
SET @max = (SELECT MAX(x) FROM bar);
INSERT INTO foo VALUES (@max);
COMMIT;
但是,在事务开始时,事务不会创建整个数据库的快照。 InnoDB使用每条记录锁定。因此,在#2和#3中,如果会话A执行您显示的查询时会话A正在更新y
,则B更新的记录可能包括也可能不包括由A修改的记录,具体取决于记录的相对顺序。这些具体的变化。另一方面,MyISAM使用表级锁,因此这不可能。首先开始的查询将锁定foo
表,而另一个查询将等待其完成才开始扫描表。
答案 1 :(得分:0)
事务用于保证数据库状态。可重复读取,因此当读取最大值时,您可以再次读取它,并且它将保持不变。
然后您设置交易
https://dev.mysql.com/doc/refman/5.6/en/set-transaction.html
然后您的代码更新x =(从z中选择max(y))
然后您提交交易
我可能错过了一些东西,但总的来说,这就是以前的举报方式。