是什么?
MVCC就是多版本并发控制,实现了【读-写冲突不加锁】,【非阻塞并发读】
MVCC只针对读已提交和可重复读,如果是读未提交,每次都是当前读
**基本思想是:**在每次【更新操作】时,旧版本的数据保存在【undo log日志中】并用【回滚指针】形成一条【版本链】,读数据的时候通过【readview视图】,拿到【版本链】中的旧数据,解决了读-写加锁效率低的问题
对数据库的并发控制:
既然有了MVCC不加锁解决读-写冲突,那么可以用MVCC再搭配乐观锁或者悲观锁去解决写-写冲突,完成对数据库的并发控制
- MVCC + 悲观锁 MVCC解决读写冲突,悲观锁解决写-写冲突。
- MVCC + 乐观锁 MVCC解决读写冲突,乐观锁解决写-写冲突。
实现原理:
主要依靠【undo log日志】、【readview视图】和记录中的【三个隐式字段】实现
- 隐式字段:
- DB_ROW_ID: B+树要求每个表都有一个主键,如果没有会自动寻找第一个非空的唯一索引作为主键,如果还是没有就自己生成一个自增主键(跟MVCC没什么关系)
- DB_TRX_ID:记录每次【增删改操作】的事务自增ID,查询不会自增
- DB_ROLL_PTR: 回滚指针,指向上一个版本记录,形成一条版本链
- undo log日志:记录每次修改前的数据,保证事务的回滚操作
- read view视图:维护了【当前未提交事务ID数组】和数组中的【最小id】和【最大id】,用来判断当前记录是否可读
-
当前记录的事务id<未提交事务的最小id,说明读的记录是已提交的,则可读
-
当前记录的事务id>未提交事务的最大id,说明则当前读的记录在 这个版本是在生成快照之后产生的,则不可读,要沿着回滚指针比较上一次事务id
-
最小id<=事务id<=事务的最大id,判断事务id是否在未提交事务id的数组中,若在说明还没提交,则不可读,不在则可读
-