MVCC基本概念
当前读
当前读 : 读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁. 对于我们日常的操作.
如 : select....lock in share mode(共享锁) , select * for update , update ,insert,delete(排他锁) 都是一种当前读.
快照读
简单的select(读不加锁) 就是快照读, 快照读读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读.
不同的事务隔离级别下不同
- Read Committed(读已提交) : 每次select 都生成一个快照读
- Repeated Read(可重复度) : 开启事务后 一个select语句才是快照读的地方(因为要保证以后读取的数据和事务开启时的数据是一致的,所以后面的select都读取的是第一个select语句的快照,并没有产生新的快照).
- Serialiazble(串行化) : 快照读就会退化为当前读.
MVCC
MVCC 也就是多版本并发控制, 它是指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQl实现MVCC提供了一个非阻塞读的功能. MVCC的具体实现,还要依赖于数据库记录中的三个隐式字段,undo log 日志,readView.
数据库记录中的三个隐式字段
当我们创建一个表的时候,除了我们规定的字段比如上面那张表有id,age,name. InnoDB引擎还会为我们创建2个或者3个隐式字段.
DB_TRX_ID : 代表最近修改的事务ID. 记录 插入这条记录 或者是 最后一次修改该记录的 事务ID -->是自增的
也就是说当我们插入这条记录或者修改这条记录,InnoDB存储引擎都会为这个DB_TRX_ID进行赋值.
BD_ROLL_PTR : 代表回滚指针, 指向这条记录的上一个版本,用于配合undo log ,指向上一个版本.
DB_ROW_ID : 代表隐式主键, 如果表结构没有指定主键,将生成该隐藏字段
只有表结构没有指定主键的时候,这个隐式字段DB_ROW_ID 才会生成.
undo log日志 , undo log 版本链
undo log 日志
回滚日志->undo log ,在insert update的时候产生的便于数据回滚的日志.(undolog日志记录的就是数据变更之前的记录情况)
当事务提交的时候或者该事务被回滚之后,undo log 日志就会有可能被删除.
什么时候这个undo log日志会被删除 ? 什么时候不会被删除呢?
- 当insert的时候,产生的 undo log 日志只在回滚的时候需要,在事务提交后,会被立即删除
- 而update,delete的时候,产生的undo log 日志不仅会在回滚的时候需要,在快照读的时候也需要,不会被立即删除
undo log 版本链
undo log版本链就是为了发生异常时,进行回滚形成的一个链表,然后根据某些规则最终决定回滚到哪个版本.
所以, 不同事务或者相同事务对同一条记录进行修改,每次修改的时候就会更新DB_TRX_ID(事务ID)和DB_ROLL_PTR(回滚指针),当有活动事务的时候,undolog里面的记录不能被删除,每个事务修改之后就会用DB_ROLL_PTR回滚指针串联起来形成一个undolog版本链.就会导致该记录的undolog生成的一条记录版本链表,记录了该记录的所有历史版本, 链表的头部就是最新的就记录,链表的尾部就是最早的旧记录.
readView
readView也就是读视图 : 是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id
readView主要包含以下四个字段 :
快照读MVCC提取数据的时候就是依据上面这四个字段.
版本链数据访问规则
对于不同的隔离级别,生成的ReadView的时机不同,
- Read Committed : 在事务中每一次执行快照读时生成ReadView
- REPEATABLE READ : 仅在事务第一次执行快照读的时候生成ReadView,后续复用ReadView
MVCC原理(RC级别)
在事务中每一次执行快照读时生成ReadView
因为所有事务执行完成之后,都会生成一个undolog版本链,每一次执行快照读时生成ReadView(RC隔离级别下),所以我们就可以根据readview里面的信息沿着undolog版本链依次与版本链数据访问规则进行比对,看符合哪条规则,如果符合版本链数据访问规则中的某一条,就把该历史版本返回
MVCC原理(RR级别)
仅在事务第一次执行快照读的时候生成ReadView,后续复用ReadView
参考 : 黑马程序员 MySQL视频黑马程序员 MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化全囊括_哔哩哔哩_bilibili