目录
已提交读(read-committed)和可重复读(repeatable-read)的底层原理:MVCC(多版本并发控制)
并发的读取方式:快照读
MVCC多版本并发控制
MVCC是多版本并发控制(Multi-Version Concurrency Control),是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别的实现,也经常称为多版本数据库。MVCC机制会生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本(系统版本号和事务版本号)。
InnoDB提供了两个读取操作:
<1>锁定读:S锁(共享锁、读锁)和X锁(排它锁、写锁)
<2>非锁定读:MVCC提供的快照读(依赖底层的技术——undo log回滚日志)
MVCC多版本并发控制中,读操作可以分为两类:
1、快照读(snapshot read):读的是记录的可见版本,不用加锁,如:select
2、当前读(current read):读取的是记录的最新版本,并且当前读返回的记录。如:insert,delete,update,select ... lock in share mode/for update
事务日志:
undo log(回滚日志)、redo log(重做日志)
undo log回滚日志的主要作用:
1.事务发生错误时回滚rollback
2.提供了MVCC的非锁定读(快照读)
undo log回滚日志底层实现机制:
MVCC:每一行记录实际上有多个版本,每个版本的记录除了数据本身之外,增加了其他手段
DB_TRX_ID:记录当前事务ID
DB_ROLL_PTR:指向undo log日志上数据的指针
已提交读(read-committed):
每次select查询时,每次执行语句的时候都重新生成一次快照(Read View)
问题:为什么已提交读无法解决“不可重复读”?
答:因为每一次select都会重新产生一次数据快照,其他事务更新后而且已提交的数据,可以实时反馈到当前事务的select结果当中!
问题:为什么已提交读无法解决“幻读”?
答:因为每一次select都会重新产生一次数据快照,其他事务增加了和当前事务查询条件相同的新的数据并且已成功commit提交,导致当前事务再次以同样的条件查询时,数据多了!
可重复读(repeatable-read):
在第一次select查询时,同一个事务开始的时候生成一个当前事务全局性的快照(Read View)。只产生一次。
问题:为什么可重复读解决“不可重复读”?
答:因为第一次select产生数据快照,其他事务虽然修改了最新的数据,但是当前事务select时,依然查看的是最初的快照数据。
问题:为什么可重复读部分解决“幻读”?
答:因为第一次select产生数据快照,其他事务虽然insert最新的数据或者select,但是当前事务select时,依然查看的是最初的快照数据。所以,可重复读解决了insert和select产生的幻读问题。但update时,当前事务是可以看见自己事务修改,更新数据的,所以产生幻读!!!
其中,最后一个select在当前事务虽然查询的是快照,但是当前读依然可视化,也可读。
快照内容读取原则:
1、版本未提交无法读取生成快照
2、版本已提交,但是在快照创建后提交的,无法读取
3、版本已提交,但是在快照创建前提交的,可以读取
4、当前事务内自己的更新,可以读到