尼恩说在前面
谈谈:mysql 事务隔离的底层原理? 谈谈:RR级隔离是如何解决幻读? 谈谈:RR级隔离如何解决幻读?什么情况下不能解决幻读? 谈谈:说说mysql 事务隔离级别的底层原理? .......
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
本文目录
- 尼恩说在前面
- ACID的I 隔离性(Isolation)如何实现?
- 并发事务三大问题:脏读、不可重复读和幻读
- (1)脏读:一个事务读取到另一个尚未提交事务的修改。
- (2)不可重复读:多次读取同一记录,数据的不同。
- (3)幻读:多次执行同一个查询,结果集数量的不同。
- 4种事务隔离级别
- 表1: 隔离级别 并发事务 三大问题之间的关系
- 表2: 隔离级别 与 具体数据操作 之间的隔离关系
- mysql 如何实现隔离机制的总结?
- RR隔离级别下是如何防止幻读的?
- 快照读和当前读
- MVCC undo log版本链
- 什么是ReadView呢?
- ReadView的核心属性
- ReadView的生成规则
- 幻读的实操演示
- 查看 Mysql 隔离级别
- 查看 Mysql 的事务提交模式
- 演示涉及到的表和操作
- 快照读场景
- 当前读场景,不会幻读
- 什么情况下,快照读场景,可能产生幻读?(例外的场景演示)
- 尼恩架构团队的塔尖 sql 面试题
ACID的I 隔离性(Isolation)如何实现?
原子性、持久性等侧重于研究事务本身不同, 隔离性呢,隔离性研究的是不同事务之间的相互影响,
并发事务三大问题:脏读、不可重复读和幻读
(1)脏读:一个事务读取到另一个尚未提交事务的修改。
尼恩解读:脏读是 读到其他事务没有提交的数据,注意,这数据还没有被其他事务提交,彻底的脏数据。 脏读 指的是 当前事务 和 其他事务没有做任何 隔离 。
(2)不可重复读:多次读取同一记录,数据的不同。
尼恩解读:幻读是 记录里边的数据变了, 但是,读到的是其他事务已经提交的数据。其他事务没有提交的数据,还是被隔离了, 隔离性稍微好点。 数据记录的数量没有, 没有 隔离 其他事务的 更新操作 。
(3)幻读:多次执行同一个查询,结果集数量的不同。
尼恩解读:幻读是结果集的层面发生了变化, 数据记录的数量变了, 没有 隔离 其他事务的 插入或删除操作 。
以上内容如果不懂,请参考后面的《尼恩Java面试宝典》 配套视频
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
4种事务隔离级别
未提交读(read uncommitted), 提交读(read committed), 重复读(repeatable read), 串行读(serializable)。
Oracle中默认的事务隔离级别是提交读 (read committed)。 对于MySQL的Innodb的默认事务隔离级别是重复读(repeated read)。
READ UNCOMMITTED(读取未提交)
允许读取尚未提交的数据变更。 这是最低的隔离级别,它可能导致脏读、不可重复读和幻读。 在这个级别,一个事务可以读取到另一个尚未提交事务的修改,这可能导致数据的不一致性。
READ COMMITTED(读取已提交)
只允许读取并发事务已经提交的数据。 这个级别可以防止脏读,但仍可能导致不可重复读和幻读。 在这个级别,每个事务只能看到它开始时的数据状态以及它提交时其他事务所做的提交。
REPEATABLE READ(可重复读取)
这是MySQL的默认隔离级别。 它确保在同一事务中多次读取同一数据时,看到的是相同的数据版本,即使其他事务在此期间修改了这些数据。 尽管可以避免脏读和不可重复读,但在这个级别下仍可能出现幻读(即在一个事务中,两次相同的查询可能会返回不同的结果集,因为其他事务在此期间插入了新的记录)。
SERIALIZABLE(可串行化)
这是最高的隔离级别。 它通过强制事务串行执行来避免脏读、不可重复读和幻读。 在这个级别,每个事务在执行时都会完全锁定它所访问的数据,从而确保数据的一致性。但这也可能导致性能下降,因为并发事务必须等待其他事务完成才能执行。
脏读(Dirty Read)特点: 一个事务读取到另一个尚未提交事务的修改。 隔离性:没有任何隔离。 不可重复读(Non-repeatable Read): 在同一个事务内,多次读取同一数据返回的结果有所不同。 隔离性: 隔离性稍微好点, 其他事务未提交的修改数据 被隔离了。 没有 隔离 其他事务的修改操作、 插入或删除操作,数据值的有可能变化 ,数据记录的数量有可能变化。 幻读(Phantom Read): 一个事务在执行两次相同的查询时,因为另一个并发事务的插入或删除操作,导致两次查询返回的结果集不同。 隔离性: 隔离性更好点, 其他事务未提交的修改数据 被隔离了。 没有 隔离 其他事务的 插入或删除操作,数据记录的数量有可能变化。
表1: 隔离级别 并发事务 三大问题之间的关系
表2: 隔离级别 与 具体数据操作 之间的隔离关系
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
mysql 如何实现隔离机制的总结?
写写隔离:(一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性 读写隔离:(一个事务)写操作对(另一个事务)读操作的影响:MVCC+ 读视图,保证隔离性
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
RR隔离级别下是如何防止幻读的?
MVCC
机制主要通过三个组件实现:隐藏字段
Undo-log
日志ReadView
。
快照读和当前读
快照读,就是读取快照数据,即快照生成的那一刻的数据。
SELECT * FROM USER WHERE ......
当前读,就是读取最新的数据,要读取最新提交的数据版本。
SELECT * FROM USER LOCK IN SHARE MODE; SELECT * FROM USER FOR UPDATE; INSERT INTO USER VALUES ...... DELETE FROM USER WHERE ...... UPDATE USER SET ......
RR和RC
这两个事务隔离级别下才会使用 快照读。在RR中,快照会在事务中第一次SELECT语句执行时生成,只有在本事务中对数据进行更改 才会更新快照。 在RC中,每次SELECT都会重新生成一个快照,总是读取最新快照数据。
MVCC undo log版本链
Undo-log日志
实现。T1
事务要查询id=1的一条行数据,此时这条行数据正在被T2
事务修改,那也就代表着这条数据可能存在多个旧版本数据,T1
事务在查询时,应该读这条数据的哪个版本呢?ReadView
,用它来做多版本的并发控制,根据查询的时机,来选择一个当前事务可见的旧版本数据读取。什么是ReadView呢?
MVCC
基于当前MySQL
的运行状态生成的快照,也被称之为读视图,即ReadView
,在这个快照中记录着当前所有活跃事务的ID
(活跃事务是指还在执行的事务,即未结束(提交/回滚)的事务)。ReadView是事务在进行快照读的时候生成的记录快照, 可以帮助我们解决可见性问题的。
ReadView的核心属性
select
操作时,MVCC
就会生成一个数据库当前的ReadView
,ReadView
属于一对一的关系(不同隔离级别下也会存在细微差异),ReadView
一般包含4个核心属性:属性 | 描述 |
---|---|
creator_trx_id | 代表创建当前这个 |
trx_ids | 表示在生成当前 |
up_limit_id | 活跃的事务列表(trx_ids)中,最小的 |
low_limit_id | 表示在生成当前 |
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
ReadView的生成规则
RR(可重复读)和RC(读已提交)
这两个事务隔离级别下有效,生成ReadView规则是不同的:在RR中, ReadView
会在事务中第一次SELECT
语句执行时生成,只有在本事务中对数据进行更改才会更新快照。在RC中,每次SELECT都会重新生成一个 ReadView
,总是读取最新版本数据。读已提交和可重复读唯一的区别在于: 1.在RC隔离级别下,是每个select都会创建最新的ReadView; 2.而在RR隔离级别下,则是当事务中的第一个select请求才创建ReadView。 除非发生了数据的修改。
幻读的实操演示
查看 Mysql 隔离级别
information_schema
中的 GLOBAL_VARIABLES
或 SESSION_VARIABLES
表来查看当前的隔离级别。-- 查看全局隔离级别
SELECT @@global.tx_isolation;
-- 查看会话隔离级别
SELECT @@session.tx_isolation;
请注意, @@global.tx_isolation
显示的是全局设置,它定义了服务器启动时的默认隔离级别。而 @@session.tx_isolation
显示的是当前会话的隔离级别,它可能会覆盖全局设置。
READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE
REPEATABLE READ
是 MySQL 默认的隔离级别,而 SERIALIZABLE
提供了最高的隔离级别,但可能会影响性能。-- 查看全局隔离级别
SHOW GLOBAL VARIABLES LIKE 'tx_isolation';
-- 设置全局隔离级别
SET GLOBAL tx_isolation = 'REPEATABLE-READ';
-- 查看会话隔离级别
SHOW VARIABLES LIKE 'tx_isolation';
-- 设置会话隔离级别
SET SESSION tx_isolation = 'READ-COMMITTED';
查看 Mysql 的事务提交模式
mysql> SHOW VARIABLES LIKE "AUTOCOMMIT";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
mysql> SET AUTOCOMMIT=0
AUTOCOMMIT=1表示开启默认提交, AUTOCOMMIT=0表示关闭默认提交需要手动提交。
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
演示涉及到的表和操作
事务A | 事务B | |
---|---|---|
t1 | begin; | begin; |
t2 | select * from t_user where age >20 and age<30; | |
t3 | insert into t_user (id, name,age) values (5, "技术自由圈——塔尖技术社群",25); | |
t4 | commit; | |
t5 | select * from t_user where age >20 and age<30; | |
t6 | commit; |
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
快照读场景
事务A | 事务B | |
---|---|---|
t1 | begin; | begin; |
t2 | select * from t_user where age >20 and age<30; | |
t3 | insert into t_user (id, name,age) values (5, "技术自由圈——塔尖技术社群",25); | |
t4 | commit; | |
t5 | select * from t_user where age >20 and age<30; | |
t6 | commit; |
事务A中,t2和t5 查询的是相同的快照,所以读取到的是相同的条数, 事务B中的t3插入数据成功,但是不会影响到事务A的快照,所以不会产生幻读。
事务B中的t3插入数据成功,但是会影响到事务A的快照,所以 会产生幻读。 大家可以自己实验
当前读场景,不会幻读
当前读,就是读取最新的数据,要读取最新提交的数据版本。
SELECT * FROM USER LOCK IN SHARE MODE; SELECT * FROM USER FOR UPDATE; INSERT INTO USER VALUES ...... DELETE FROM USER WHERE ...... UPDATE USER SET ......
事务A | 事务B | |
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
什么情况下,快照读场景,可能产生幻读?(例外的场景演示)
RR和RC
这两个事务隔离级别下才会使用 快照读。在RR中,快照会在事务中第一次SELECT语句执行时生成,只有在本事务中对数据进行更改时, 才会生成undo log,并且更新read view。 在RC中,每次SELECT都会重新生成一个快照,总是读取最新快照数据。
事务A | 事务B | |
尼恩提示: 以上内容比较复杂,后面会在《尼恩Java面试宝典》配套视频中,进行详细解读。
尼恩架构团队的塔尖 sql 面试题
sql查询语句的执行流程:
什么是回表?什么是 索引下推 ?
mysql 索引失效
MVCC
binlog、redolog、undo log
空窗1年/空窗2年, 如何 起死回生 ?
上岸奇迹:中厂大龄34岁,被裁8月收一大厂offer, 年薪65W,转架构后逆天改命!
案例2:42岁被裁2年,天快塌了,急救1个月,拿到开发经理offer,起死回生
案例3:35岁被裁6个月, 职业绝望,转架构急救上岸,DDD和3高项目太重要了
案例4:失业15个月,学习40天拿offer, 绝境翻盘,如何实现?
100W 年薪 大逆袭, 如何实现 ?
100W案例,100W年薪的底层逻辑是什么? 如何实现年薪百万? 如何远离 中年危机?
如何 逆天改命,包含AI、大数据、golang、Java 等
实现职业转型,极速上岸
关注职业救助站公众号,获取每天职业干货
助您实现职业转型、职业升级、极速上岸
---------------------------------
实现架构转型,再无中年危机
关注技术自由圈公众号,获取每天技术千货
一起成为牛逼的未来超级架构师
几十篇架构笔记、5000页面试宝典、20个技术圣经
请加尼恩个人微信 免费拿走
暗号,请在 公众号后台 发送消息:领电子书
如有收获,请点击底部的"在看"和"赞",谢谢