MVCC的理解:
1.MVCC,多版本并发控制,指的是维持一个数据的多个版本,使得读写没有冲突。在程序中实现事务内存。在数据库管理系统中,实现对数据库的并发访问。
在MySql,InnoDB中的实现主要是为了数据库的并发性能。
处理读写的冲突,在读写冲突时,做到不加锁,非阻塞并发读。
读操作的两个方式:
1.当前读
当前读,顾名思义,读取记录的最新版本,读取时还要保证其他并发事务不能修改当前记录。
像是共享锁,select for update,update,insert,delete 都是当前读。
2.快照读(提高数据库的并发查询能力)
前提:隔离级别不能是串行级别,串行级别下的快照读会退化成当前读。
像是不加锁的select就是一种快照读,即不加锁非阻塞读
为了提高并发性能,出现了快照读的方式,它的实现是基于多版本并发控制(MVCC)
可以认为MVCC是行锁的一个变种,它在很多情况下,避免了加锁操作,降低开销。
那么既然是基于多版本,即快照读可能读到的不是当前数据的最新版本,可能是之前的版本
MVCC解决的问题
数据并发的场景有三种
1.读读并发:不存在问题,不需要并发控制
2.读写并发:有线程安全问题,可能会造成事务隔离性问题,遇到脏读,幻读,不可重复读
3.写写并发:有线程安全问题,可能会有更新丢失
MVCC解决的就是读写并发的问题,是一种无锁并发控制。
也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库快照,这样就解决了两个问题:
1.在并发读写操作数据库时,可以做到读操作和写操作互不阻塞,提高数据库并发性能
2.解决读写并发时可能会出现的脏读,幻读,不可重复读等事务隔离问题
MVCC原理
在MySql中,MVCC的实现主要依赖记录中的三个隐藏字段,undolog,read View三个组件来实现的
隐藏字段
RowId: 隐藏主键,如果表中没有指定主键,会自动生成一个id作为主键
TrxId:最近修改事务Id,记录了创建这条记录或是最后一次修改这条记录的事务Id
RollPtr:回滚指针,用于配合undoLog这条记录的上一个版本
undoLog(回滚日志)
在进行增删改操作时记录的方便回滚的日志
在进行insert操作的时候,记录的undoLog只在回滚的时候需要,并且在事务提交后删除
在进行delete,update操作的时候,记录的undoLog不仅在事务回滚的时候需要,在快照读的时候也需要。只有在快照读和事务回滚都不涉及该日志时,才会被线程统一清除。
也就是delete_bit为true且表中事务Id相对于purge线程的read view可见时,才删除
浅析InnoDB purge线程_老叶茶馆_的博客-CSDN博客
Read View
ReadView即一致性视图,用来判断版本链中的哪个版本是当前事务可见的。
- RC和RR隔离级别之间一个非常大的区别就是——它们生成ReadView的时机不同!!
- RC——在一个事务中,每次读取数据前都生成一个ReadView。
- RR——在一个事务中,只在第一次读取数据时生成一个ReadView。
RC(READ COMMITTED)
RR(REPEATABLE READ)
总结:MVCC是利用记录的版本链和ReadView,来控制并发事务访问相同记录时的行为。