Repeatable Read isolation level 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
处失败,但不是这种混合和匹配。
这里有什么见解吗?
推荐答案
https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html
一致读取意味着InnoDB使用多版本控制向查询呈现某个时间点的数据库快照。查询会看到在该时间点之前提交的事务所做的更改,而不会看到后来或未提交的事务所做的更改。此规则的例外情况是,查询会看到同一事务中较早的语句所做的更改。此异常会导致以下异常:如果更新表中的某些行,SELECT会看到更新的行的最新版本,但也可能会看到任何行的较旧版本。如果其他会话同时更新同一个表,则异常情况意味着您可能会看到该表处于数据库中不存在的状态。
重要的条件是,如果您更改了行,您的一致读取将被"刷新",因此它包括您刚刚所做的更改。
但如果您更新,它始终是行的最新版本,而不是事务的一致读取可以查看的版本。因此,如果另一个事务已经进行了该更改,则您的更新可能不会产生任何净效果。这就是您观察到的情况。
因此,您的事务发出了更新,但未更改行。
这可能不是您希望InnoDB的行为方式,但它确实是这样的。
这篇关于可重复读取隔离级别SELECT VS UPDATE...WHERE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:可重复读取隔离级别SELECT VS UPDATE...WHERE


基础教程推荐
- 无法在 ubuntu 中启动 mysql 服务器 2021-01-01
- 如何在 SQL Server 的嵌套过程中处理事务? 2021-01-01
- 使用pyodbc“不安全"的Python多处理和数据库访问? 2022-01-01
- Sql Server 字符串到日期的转换 2021-01-01
- SQL Server 2016更改对象所有者 2022-01-01
- 将数据从 MS SQL 迁移到 PostgreSQL? 2022-01-01
- SQL Server 中单行 MERGE/upsert 的语法 2021-01-01
- ERROR 2006 (HY000): MySQL 服务器已经消失 2021-01-01
- SQL Server:只有 GROUP BY 中的最后一个条目 2021-01-01
- 在 VB.NET 中更新 SQL Server DateTime 列 2021-01-01