- mysql 可以查询当前事务隔离级别
默认是RR
repeatable-read
- 如果要测脏读 要配成未提交读 RU
读到了未提交的数据。
3.演示不可重复读
要改成提交读 RC
这个是指事务还未结束,其他事务修改了值。导致我两次读的不一样。
4.RR–可以解决不可重复读
小总结:
RU-》有脏读-》为了解决脏读来一个RC,读已提交-》有不可重复读的问题-》为了解决不可重复读的问题来一个RR。-》有幻读-》
5.在RR隔离级别下,快照读的数据范围是:
✅ 事务首次SELECT时已提交的数据 + 当前事务自身的修改
6.当前读 vs 快照读
快照读(普通SELECT)→ 依赖Read View,不包含未提交数据
。
当前读(SELECT FOR UPDATE)→ 读取最新数据(含未提交),通过锁机制实现
。
7.事务开始 ≠ 快照生成
RR下快照在第一个SELECT时生成,而非BEGIN执行时
。例如:
sql
复制
BEGIN; – 事务开始,但未生成Read View
SELECT …; – 生成Read View并记录快照
8.innodb 的MVCC+间隙锁,让RR级别就解决了幻读。
9.MVCC
mutiversion concurrency control
多版本并发控制器
事务隔离级别的无锁的实现方式,提高事务的并发性能。
是事务隔离级别的一种底层实现方式。
并不是所有的隔离级别都用到MVCC。
4级别
读未提交–>脏读
读已提交—>不可重复读
可重复读----》幻读
串行化 Serializable S SER 锁表。
然后幻读–》事务1对整个表进行汇总
如对某字段求和。 但是另外一个事务插入了一条数据。
幻读与不可重复读看起来像,但是幻读往往针对整张表,而不可重复读是针对某一条或者几条数据。
MVCC–3个隐藏列
1.事务ID
2.DB_ROLL_PTR
如果回滚可以链到之前的数据。
3.无主键时有一个row id。这个不重要
历史数据存储于 undo log。
若读已提交,从undo log中找历史数据。
若RC。每次查询,创建一个ReadView
定位到undolog。。。
当前事务 正在并发的事务 未开始的
进行中的事务—》还未提交的有个最小的
最大的 可能还未开始。
自己写的可以。
快照之前已提交的可以。
如果是快照瞬间,活跃事务做的。
读已提交是不行的。
最小最大中—只有它自己的OK。
小于最小的 一直OK
大于最大的 一直不OK.
徐庶讲的是读已提交下的MVCC。
另外的也讲了:
读未提交,不需加锁,也不需MVCC
串行化—表锁 无需MVCC
可重复读—》只有在第一次查询建快照。
所以RC RR MVCC机制大体相似,只是是否每次查询建快照的区别。
简单理解就是一次RC里面做了多次RR。没什么意义的评论。
10.关于徐庶说RR无法解决幻读的争议。
字节面试官说MVCC+间隙锁解决了幻读
刚刚看的视频,UP演示的也是RR能解决幻读。
总结:
数据库的隔离级别分四种:
读未提交 RU
读已递交 RC
可重复读 RR
序列化读 S
其中读未提交 RU有脏读问题。意思是当前事务能够读到其他事务未提交的数据,若发生回滚,导致脏读。
读已提交模式下,存在在同一个事务中读取一个查询两次结果不同的问题。这个是由于事务进行期间,其他事务提交修改了数据。如果不想这种事情发生,可以设置可重复读,RR隔离级别。
mysql 的默认RR隔离级别已经很强,不仅解决了不可重复度的问题,甚至能够通过MVCC+间隙锁解决大部分幻读。
幻读与不可重复度在表现上类似,但是幻读一般是一些基于全表的统计案例。而不可重复度是针对单条或者少量的数据的查询。
间隙锁的原理是不仅一行一行的把数据锁住,还锁住数据与数据之间的间隙。
MVCC全称是Multiversion concurrency control。它是mysql数据库关于隔离级别读已提交和可重复读的一种无锁实现方式,提升性能。
具体的原理是:
首先mysql有三个隐藏列,一个是当前事务ID,一个是若发生回滚,指向旧数据UndoLog的指针。另外一个是rownum与本主题无关。
对于可重复读隔离级别,在事务第一次select时,生成readView。记录当前未完成的事务ID最小值,以及最大值。
源码进行了四次判断,较复杂,我对它进行了逻辑简化如下:
快照抓取到一个事务ID范围。严格在这个范围之前的,代表快照时已经提交。所以能查到。在这个范围之后的,代表是快照后新启的事务,应该看不到。而在这个事务当中,只有当前事务它自己做的数据修改或者创建能看到,其他事务ID的数据不可见。
后续同一个事务的其他读,依然基于此快照实现。
以上是可重复读基于MVCC的实现。
读已提交的底层实现与可重复读类似,都使用了MVCC。只是读已提交每次查询都建立一个ReadView,这样就能达成每次都查询已提交的数据。
对于读未提交,直接读最新数据即可,既不需要上锁,也不需要使用MVCC。
对于序列化读,会使把所有数据都加Next-Key Lock
也就是行锁(Record Lock )加间隙锁(Gap Lock)。影响性能,一般只在严格要求绝对安全的金融、银行等企业使用。
纠正字节面试官的一个点 mysql 的 innoDb 使用MVCC + Next-Key Lock解决幻读。而不是MVCC+间隙锁。