lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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_idroll_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_idlow_limit_id之间,但不在Read View的trx_ids列表中,说明该记录是已提交事务更新或者插入的,对当前事务可见。
  • 如果记录的trx_id在Read View的up_limit_idlow_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来实现快照读算法,从而避免了加锁带来的开销和风险。

 

posted on 2023-06-10 16:27  白露~  阅读(78)  评论(0编辑  收藏  举报