什么是MVCC
mvcc是一种并发控制的方法,在数据库中用来实现对数据的并发访问,mvcc在mysqlinnodb存储引擎中是为了提高数据库访问并发能力,用更好的方式去处理读-写冲突,做到有读写冲突时能做到不加锁、非阻塞并发读
当前读、快照读
-
当前读
在看mvcc的之前我了解当前读,当前读是指读取数据的时候读取的是当前记录的最新版本,并且会对读取的记录加锁,保证其它的事务不能对该事务做修改。
触发当前读的条件,insert、update、delete操作都会先读区数据,这时候的读都是当前读,还有select from for update、lock in share mode也会触发当前读
2. 快照读
不加锁的select就是快照读,它是非阻塞的,它读取的是当前事物可见的版本数据(可能是历史版本的数据)
mvcc
mvcc就是为了实现快照读而产生的,它的实现基于三部分,分别是:ReadView、undo日志、记录上的隐藏字段(db_trx_id(操作事务的id)、db_roll_prt(回滚指针))
ReadView:事务进行快照读时创建的读视图,该视图记录着当前数据库活跃着的事务id(每个事物创建会产生一个事务id),readview的内部结构
RU 串行化 无需使用mvcc,串行化的场景下,快照读会直接升级为当前读,下面的列子是读已提交的场景
MVCC的几个关键点:
1:Readview
2:undo多版本日志
3:记录行的隐藏列 db_trx_id(操作的事物id),db_roll_prt(回滚指针)
数据库的记录:
事物操作过程
事物级别 read commit :
1:事物80开启事物
2:事物100开启
3:事物100执行第一次查询id=1的记录
创建的ReadView 为:
创建undo日志 ,只有一条记录:
此时从这条记录中发现他的db_trx_id=70,发现它并不在rw的mids中,且小 于最小事物ID,
说明该记录为可读记录,查询到结果为 冬瓜
4:事物101开启
5:此时事物80执行update操作
会在undo中为id=1的记录增加一条undo记录,其中db_trx_id为80,且该版本录指向上一条记录:
6: 事物100执行第二次查询
创建ReadView:
从undo中查找id=1的数据版本记录
1)先找到id==1的第一条数据,发现他的db_trx_id=80,80在mids中,说明该事物还未提交,
2)查找链表下一条数据,发现db_trx_id=70,70并不在rw的mids中且小于最小事物ID,
查询的结果为name= 冬瓜
7:事物80执行commit;
8:此时事物101执行update操作
会在undo日志中为id=1的数据增加一个新的版本数据:
9:事物100执行第三次查询:
1):创建ReadView:
2):从undo中查找id=1的数据版本记录
3):查询记录
<1>.先找到id==1的第一条数据,发现他的db_trx_id=101,101在mids中,说明该事物还未提交
<2>.找到第二条记录,发现他的db_trx_id = 80,80小于最小事物id,说明该事物在创建rw时已经提交了
<3>. 查询出来的数据未name = 西瓜
事物级别 RR和(可重复读) : 在第一次查询的时候建readview,事物结束之前都不在重新创建