什么是MVCC?
MVCC是一种并发控制方法,一般在数据库管理系统中,实现数据库的并发访问。
可以使用乐观锁和悲观锁来实现。
MVCC的作用?
可以在不加锁的情况下解决读写问题,同时还可以解决脏读,幻读,不可重复读等事务隔离问题(但不能解决更新丢失问题)。
各数据库中MVCC实现并不统一
InnoDB的MVCC,是通过在每行纪录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建版本号,一个保存了行的删除版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行纪录的版本号进行比较(在可重复读隔离级别下)。
为什么需要MVCC?
在应对高并发事务时,MVCC比单纯的加锁更高效。
首先来说数据库的并发场景有三种,读读,读写和写写
读读:不会存在任何问题,也不需要并发控制
读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读、幻读、不可重复读,需要MVCC控制。
写写:有线程安全问题,可能会存在更新丢失问题。
MVCC是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。
所以MVCC可以为数据库解决的问题是:
-
在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
-
同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题
MVCC的特点:
-
1、解决读写之间的堵塞问题
-
2、不使用锁
-
3、解决一致性读的问题,我们读数据时,只能看到这个节点以前事务提交修改的数据
底层原理
-
1、主要依赖三个隐藏关键字(事务id,上个版本数据在undo log中的地址、隐藏id)、undo log日志,Read View;
-
2、事务每次更新都会在undo log 中新增数据,递增事务id,并记录上个版本的数据地址,构成版本链
-
3、读数据的时候会生成ReadView,ReadView中记录了当前活跃事务id,查询版本链中在活跃事务id之前的才可见
-
4、在读已提交中,每次读都会生成 ReadView 可重复读中,只有第一次读生成ReadView
readview视图
readview叫做读视图,是事务在进行快照读操作的时候产生的视图,此视图保存的并不是实际的数据,而是事务相关的信息,主要的用途是来进行可见性判断;
当我们用select读取数据时,这一时刻的数据会有很多个版本(例如上图有四个版本),但我们并不知道读取哪个版本,这时就靠readview来对我们进行读取版本的限制,通过readview我们才知道自己能够读取哪个版本。
当前读、快照读和MVCC的关系:
MVCC 多版本并发控制是维持一个数据的多个版本,使得读写操作没有冲突的概念,只是一个抽象概念,并非实现,因为 MVCC 只是一个抽象概念,要实现这么一个概念,MySQL 就需要提供具体的功能去实现它,(快照读就是 MySQL 实现 MVCC 理想模型的其中一个非阻塞读功能)。而相对而言,当前读就是悲观锁的具体功能实现,要说的再细致一些,快照读本身也是一个抽象概念,再深入研究。MVCC 模型在 MySQL 中的具体实现则是由 3 个隐式字段,undo 日志 ,Read View 等去完成的。