MVCC的定义
MVCC,即多版本并发控制,是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。MVCC的目的是为了提高数据库的并发性能,用更好的方式去处理读写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。
MVCC的目的
在MySQL中,InnoDB存储引擎实现了MVCC机制,主要用于解决事务隔离级别为读已提交(Read Committed)和可重复读(Repeatable Read)下的数据一致性问题。在这两种隔离级别下,InnoDB使用快照读(Snapshot Read)来读取数据,而不是加锁读(Lock Read),从而避免了加锁带来的性能开销和死锁风险。
MVCC的实现原理
MVCC的实现原理主要依赖于每一行记录中两个隐藏字段,undo log,ReadView等。
那么,InnoDB是如何实现快照读的呢?这就涉及到MVCC的底层原理。在本文中,我们将介绍以下几个方面:
- InnoDB中每行记录的隐藏列
- InnoDB中的undo log
- InnoDB中的Read View
- InnoDB中的快照读算法
InnoDB中每行记录的隐藏列
在InnoDB存储引擎中,每一行记录都有两个隐藏列:trx_id
和roll_pointer
。如果表中没有主键和非NULL唯一键时,则还会有第三个隐藏的主键列row_id
。
trx_id
:记录操作该数据事务的事务ID,也就是事务版本号。每个事务开始前,都会从数据库获得一个自增长的事务ID,可以从事务ID判断事务的执行先后顺序。roll_pointer
:这个隐藏列就相当于一个指针,指向回滚段(Rollback Segment)的undo log。undo log用于记录数据被修改前的信息,在事务回滚或者快照读时需要用到。row_id
:单调递增的行ID,不是必需的,占用6个字节。只有在表中没有主键和非NULL唯一键时才会生成。
InnoDB中的undo log
undo log,回滚日志,用于记录数据被修改前的信息。在表记录修改之前,会先把数据拷贝到undo log里,如果事务回滚,即可以通过undo log来还原数据。
可以这样认为,当delete一条记录时,undo log 中会记录一条对应的insert记录,当update一条记录时,它记录一条对应相反的update记录。
undo log有什么用途呢?
- 事务回滚时,保证原子性和一致性。
- 用于MVCC快照读。
InnoDB中的Read View
Read View是InnoDB存储引擎为了实现快照读而创建的一个数据结构。它保存了当前活跃(未提交)事务列表以及当前系统最大事务ID等信息。通过Read View可以判断某个版本的数据是否对当前事务可见。
Read View包含以下几个字段:
creator_trx_id
:创建该Read View的事务ID。low_limit_id
:当前系统最大事务ID+1。up_limit_id
:创建该Read View时活跃事务列表中最小的事务ID。trx_ids
:创建该Read View时活跃(未提交)事务列表。
InnoDB中的快照读算法
快照读算法是InnoDB存储引擎根据Read View和undo log来判断某个版本的数据是否对当前事务可见的算法。它的基本思路如下:
- 如果记录的
trx_id
小于Read View的up_limit_id
,说明该记录在Read View创建之前就已经存在,且没有被更新过,对当前事务可见。 - 如果记录的
trx_id
大于等于Read View的low_limit_id
,说明该记录在Read View创建之后才插入或者更新,对当前事务不可见。 - 如果记录的
trx_id
在Read View的up_limit_id
和low_limit_id
之间,但不在Read View的trx_ids
列表中,说明该记录是已提交事务更新或者插入的,对当前事务可见。 - 如果记录的
trx_id
在Read View的up_limit_id
和low_limit_id
之间,且在Read View的trx_ids
列表中,说明该记录是未提交事务更新或者插入的,对当前事务不可见。此时需要根据记录的roll_pointer
指向的undo log来还原该记录的前一个版本,然后重复上述步骤,直到找到一个对当前事务可见的版本或者不存在为止。
MVCC的应用场景和限制
- MVCC只在已提交读(Read Committed)和可重复读(Repeatable Read)两个隔离级别下工作,其他两个隔离级别和MVCC是不兼容的。
- MVCC只适用于快照读(普通的select语句),不适用于当前读(加锁的select语句)。
- MVCC可以解决不可重复读(同一条记录多次读取内容不一致)的问题,但不能解决幻读(同一范围多次读取结果集不一致)的问题。
MVCC的优缺点是:
- 优点:
- MVCC在大多数情况下代替了行锁,实现了对读的非阻塞,读不加锁,读写不冲突。
- MVCC可以提高数据库的并发性能和数据一致性,避免了加锁带来的开销和风险。
- MVCC可以支持多种隔离级别,如读已提交和可重复读,通过不同的Read View生成策略来实现。
- 缺点:
- MVCC需要额外的存储空间来保存每行记录的隐藏列和undo log。
- MVCC需要做更多的行维护和检查工作,如遍历版本链,比较事务ID,还原数据版本等。
- MVCC不适用于读未提交和串行化两种隔离级别,前者存在脏读问题,后者需要加锁实现。
总之,MVCC是一种并发控制的方法,利用了每行记录的隐藏列、undo log和Read View来实现快照读算法。它有利于提高数据库的并发性能和数据一致性,但也有一些额外的开销和限制。在使用MVCC时,需要根据具体的业务场景和需求来选择合适的隔离级别和事务策略。
总结
MVCC是一种并发控制的方法,用于提高数据库的并发性能和数据一致性。InnoDB存储引擎实现了MVCC机制,主要用于读已提交和可重复读两种隔离级别下的快照读。InnoDB利用每行记录的隐藏列、undo log和Read View来实现快照读算法,从而避免了加锁带来的开销和风险。