mysq RR级别下,事物中 select语句 是当前读还是快照读?
在此补充参考答案,希望对感兴趣的人给予帮助:
DML语句:insert、update、delete,本身就会加锁(此处缺少前提条件,据说在RU下不加锁,欢迎大家补充官网信息)
事物 和 锁/MVCC 是两个概念,是辅助完成事物
RC:使用当前读,SELECT ... LOCK IN SHARE MODE 或 SELECT ... FOR UPDATE、解决脏读
RR:使用MVCC(快照读),select 一直是快照值,解决不可重复读和脏读,防不住insert语句,也就是幻读
RS:使用间隙锁CAP(前开后闭),两个数据行中间加锁,解决幻读
上述符合所有的理论假设
在 MySQL 的 Repeatable Read(RR)隔离级别下,事务中的 SELECT 语句是快照读,也就是读取事务开始时的数据快照,而不是当前的数据。这意味着在事务中执行的 SELECT 语句不会读取其他事务已经提交的数据,也不会受到其他事务正在修改的数据的影响。
MySQL 的脏读问题是指在事务中读取到了其他事务未提交的数据。在 RR 隔离级别下,由于事务只能读取自己开始时的数据快照,因此不会出现脏读问题。但是,RR 隔离级别下仍然可能出现幻读和不可重复读问题,需要根据具体情况选择合适的隔离级别来解决。
快照 加锁后变成当前
RR(Repeatable Read)隔离级别下,事务中的 SELECT 语句是快照读(Snapshot Read)
也称为一致性非锁定读(Consistent Nonlocking Read)。
快照读在事务开始时,MySQL 会为每个事务创建一个快照,该快照包含了当前数据库中所有数据的一个副本。在事务执行期间,所有的 SELECT 语句都会从这个快照中读取数据,而不是直接从数据库中读取数据。因此,即使其他事务对数据库中的数据进行了修改,当前事务中的 SELECT 语句也只会读取到事务开始时的数据快照,而不会读取到其他事务修改后的数据。
需要注意的是,快照读并不会对其他事务造成阻塞,因为它不会对数据库中的数据进行加锁。但是,如果当前事务中的某个 SELECT 语句需要读取到其他事务修改后的数据,那么它可能会读取到不一致的数据,因为快照读只能保证读取到一致性的数据快照,而不能保证读取到最新的数据。
比如 A 执行范围查询:select * from table where age > 10,查到了一条数据 X。然后事务 C 72 插入了一条数据,事务 A 再次查询时,可以查到两条数据 X 和 Y。但是 Y 的版本链上事务 id 等于 72,大于最大事务 id 60,说明是事务 A 发起查询后,当然是不可读到的了,所以事务 A 还是只能读到数据 X。