可重复读取隔离级别SELECT VS UPDATE…WHERE
本教程将介绍可重复读取隔离级别SELECT VS UPDATE...WHERE的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。
问题描述
也许你可以在这里为我解释一些事情:
DB=MySQL 5.7
存储引擎:InnoDB
隔离级别:可重复读取
下表:
---------------
|MyTable|
---------------
| PK | Concur |
---------------
| 3 |2 |
---------------
此时我没有正在进行的事务,我选择此记录,如下所示
SELECT * FROM MyTable WHERE PK = 3
并将结果存储在我的程序中。
我现在启动一个数据库事务。
事务开始后,外部进程将PK
=3的记录的Concur
从2递增到3。
我尚未再次从事务内的该表中读取。
我从我的事务内部发出以下查询:
UPDATE MyTable SET Concur = 3 WHERE PK = 3 AND Concur = 2
这将通过0 records affected
成功。很明显,它会根据我的事务开始后更改的数据进行评估。
仍在事务中,我随后查询:
SELECT * FROM MyTable WHERE PK = 3
它将向我返回PK = 3 and Concur = 2
的记录,这些值是事务之前的值。
为什么SELECT
和UPDATE ... WHERE
的行为不同,我缺少什么?
我认为UPDATE ... WHERE
语句要么直接失败,而不是在0条记录受到影响的情况下成功,要么在那里成功,但有1条记录受到影响,然后在随后的COMMIT
处失败,但不是这种混合和匹配。
这里有什么见解吗?
推荐答案
一致读取意味着InnoDB使用多版本控制向查询呈现某个时间点的数据库快照。查询会看到在该时间点之前提交的事务所做的更改,而不会看到后来或未提交的事务所做的更改。此规则的例外情况是,查询会看到同一事务中较早的语句所做的更改。此异常会导致以下异常:如果更新表中的某些行,SELECT会看到更新的行的最新版本,但也可能会看到任何行的较旧版本。如果其他会话同时更新同一个表,则异常情况意味着您可能会看到该表处于数据库中不存在的状态。
重要的条件是,如果您行,您的一致读取将被"刷新",因此它包括您刚刚所做的更改。
但如果您更新,它始终是行的最新版本,而不是事务的一致读取可以查看的版本。因此,如果另一个事务已经进行了该更改,则您的更新可能不会产生任何净效果。这就是您观察到的情况。
因此,您的事务发出了更新,但未行。
这可能不是您希望InnoDB的行为方式,但它确实是这样的。
好了关于可重复读取隔离级别SELECT VS UPDATE...WHERE的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。