MVCC和undo log

MVCC多版本并发控制

MVCC是多版本并发控制(Multi-Version Concurrency Control,简称MVCC),是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别的实现,也经常称为多版本数据库。MVCC机制会生成一个数据请求时间点的一致性数据快照 (Snapshot), 并用这个快照来提供一定级别 (语句级或事务级) 的一致性读取。从用户的角度来看,好象是数据库可以提供同一数据的多个版本(系统版本号和事务版本号)。

MVCC多版本并发控制中,读操作可以分为两类:

快照读(snapshot read)

读的是记录的可见版本,不用加锁。如 select

当前读(current read)

读取的是记录的最新版本,并且当前读返回的记录。如insert,delete,update,select…lock in share mode/for update

MVCC:每一行记录实际上有多个版本,每个版本的记录除了数据本身之外,增加了其它字段

DB_TRX_ID:记录当前事务ID

DB_ROLL_PTR:指向undo log日志上数据的指针

已提交读:每次执行语句的时候都重新生成一次快照(Read View),每次select查询时。

可重复读:同一个事务开始的时候生成一个当前事务全局性的快照(Read View),第一次select查询时。

快照内容读取原则

1、版本未提交无法读取生成快照

2、版本已提交,但是在快照创建后提交的,无法读取

3、版本已提交,但是在快照创建前提交的,可以读取

4、当前事务内自己的更新,可以读到

已提交读和可重复读的问题

已提交读(READ-COMMITTED)和可重复读(REPETABLE-READ)的底层实现就是使用了 MVCC(多版本并发控制),其提供了并发读取方式 快照读;

innodb提供了两个读取操作:锁定读 和 非锁定读,MVCC提供了一个快照读,依赖于底层的undo log 即回滚日志

已提交读

已提交读解决了 脏读的问题,但没有解决幻读问题,是因为:

每一次select都会产生一次新的数据快照,但必须满足数据已被事务正确commit了。

但是没法解决 不可重复读,因为,每次select都会产生一次新的数据快照,其他事务更新后且已commit的数据,可实时反馈到当前事务的select中,所以解决了脏读问题。

没有解决幻读是因为每次select都会产生一次新的数据快照,其他事务增加了新的记录行并且已成功提交,导致当前事务以同样条件查询时,出现记录数的改变了。

可重复读

一个事务中只有第一次select产生快照,且只产生一次,这样后面再select都是查看第一次的快照,例如:
先设置两个会话都为可重复读级别并开始事务,然后会话2先查询产生快照

MVCC和undo log_第1张图片

紧接着,会话1 修改该行记录:update user set age = 20 where id=7;

然后会话2 再次进行相同查询结果仍相同

MVCC和undo log_第2张图片

这就是因为,select第二次就是用第一次select保存的快照了

正因如上所述,能够解决了不可重复的问题。同时也部分解决了幻读的问题,但是当前事务自己做的事务修改和更新数据是能被 select 出来的

undo log回滚日志主要作用

事务发生错误时回滚 rollback;

提供了MVCC的非锁定读(快照读)undo logo

MVCC和undo log_第3张图片

你可能感兴趣的:(MySQL,数据库,mysql)