MySQL笔记(3):事务隔离
自存笔记,学习MySQL实战45讲
第三讲:事务隔离
多事务同时执行的问题
- 脏读:某个事务读取到了修改完未提交的数据
- 不可重复读:同一事务,两次读取某行数据,结果不一致(针对单行数据)
- 幻读:同一事物,两次相同的查询,结果集不一样(符合条件的记录被新增或删除
隔离级别
读未提交
- 一个事务还未提交时,它做的更改就可以被看见
- 自动实现
- 会出现“三读”问题
读已提交
- 一个事务提交后,它做的更改才可被看见
- mvcc实现
- 会出现不可重复读、幻读问题
可重复读
- 一个事务从启动到结束,看到的数据始终一致
- mvcc实现
- 按照SQL标准,可重复读的隔离级别仅能保证“事务内多次读取同一行数据,数据内容一致”(解决不可重复读),不能保证“结果集的行数一致”(幻读)
- innoDB通过mvcc+间隙锁解决不可重复读和幻读问题
串行化
- 对每一行数据,读操作加读锁,写操作加写锁,当读写锁冲突时,后访问的事务必须等待前一个事务结束才能继续执行
- 加锁实现
- 不出问题
隔离的实现——MVCC
- 多版本并发控制
- 通过为数据行维护多个版本,让读操作可以不加锁的访问历史数据,避免读写冲突
大白话
核心思路:留存数据的历史记录
假设有一张学生成绩表,某行数据为张三,数学,90分
当数据被修改时,比如改到85分,不直接覆盖数据,而是:
- 把旧数据存在“历史版本”(undolog)
- 新数据写在当前版本,并记录“谁改的”(事务id),这样数据有了多个版本:旧版本(90分,事务1改的)、新版本(85,事务二改的)
读数据时:根据 “时间线” 决定看哪个版本
每个事务启动时,就像拿到一个 “时间戳”(事务 ID,比如 100、200、300,递增的)
读数据时,数据库会生成一个 “快照”(Read View),记录两件事:
- 当前有哪些事务还没提交(比如事务 200、300 在运行中)
- 我自己的事务 ID 是多少(比如 100)
然后按规则判断:
- 如果旧版本的事务 ID 比我早(比如 100 之前的 99),说明这个版本在我启动前就提交了,我能看到它(旧数据有效)
- 如果新版本的事务 ID 比我晚(比如 200、300),说明这个版本是我启动后才改的,而且对应的事务还没提交,我看不到它(只能看到旧数据)
- 如果新版本的事务 ID 和我同时存在(比如我是 100,它是 150 但没提交),它还没写完,我也看不到,只能看旧数据。
总结
MVCC通过“多版本数据+读视图”实现无锁读技术,核心是让读操作访问历史版本而非实时数据,从而在保证事务隔离性的同时提升并发能力
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.