mvcc多版本并发控制

定义

mvcc(Multiversion Concurrency Control)多版本并发控制,是现代数据库(包括Mysql、Oracle、PostgreSQL等)引擎实现中常用的处理读写冲突的手段,目的在于提高数据库并发场景下的吞吐性能。

  • 说白了,mvcc就是“维持一个数据的多个版本“。
  • 在Mysql中,mvcc只在读取已提交(Read committed) 和 重复读(Repeatable Read)两个事务级别下有效(Read uncommitted隔离级别下,读写都不加锁,Searalizabel隔离级别下,读写都加锁,也就不需要mvcc了)。
  • 其是通过undo日志中的版本链和ReadView一致性视图来实现的。mvcc就是在多个事务同时存在时,select语句找寻到具体是版本链上的哪个版本,然后再找到的版本上返回其中所记录的数据的过程。

作用

mvcc在mysql innodb中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

什么是当前读 和 快照读

在学习mvcc多版本并发控制之前,必须先了解一下,什么是mysql innodb下的当前读和快照读。

当前读

定义:读取到的记录是最新版本,读取时还要保证其他并发事务不能修改当前记录,灰度读取的记录进行加锁。
像select lock in share mode(共享锁),select for update,update ,insert , delete 这些操作都是一种当前读。

快照读

定义:
像不加锁的select操作就是快照读,即不加锁的非阻塞读。
快照读的前提是隔离级别不是串行,串行级别下的快照读会退化为当前读。
之所以出现快照读的情况是,是基于提高并发性能的考虑,快照读的实现是基于多版本控制,即mvcc,可以认为mvcc是行锁的一个变种,但他在很多情况下,避免了加锁操作,降低了开销。

实现原理

mvcc是基于undo log,隐藏字段,ReadView(读视图)实现的。

undo log(回滚日志)

undo log记录的是逻辑日志,也就是Sql语句。
比如:当我们执行一条insert语句时,undo log就记录一条相反的delete语句。

作用

  1. 回滚事务时,回到修改前的数据。
  2. 实现mvcc。

隐藏字段

当我们创建一张表时,innodb引擎会增加2哥隐藏字段。

  • DB_TRX_ID(最近一次提交事务的id)
    修改表数据时,都会提交事务,每个事务都有一个唯一的id,这个字段就记录了最近一次提交事务的id。
  • DB_ROLL_PTR(上个版本的地址)
    修改数据时,旧版本的数据都会被记录到undo log日志中,每个版本的数据都有一个版本地址,这个字段记录的就是上个版本的地址。

表记录和undo log历史数据组成了一个版本链

Read View 读视图

在事务中,执行sql查询,就会生成一个读视图,是用来保证数据的可见性,即读到undo log 种哪个版本的数据。

  • 快照读一般是读取的是历史版本的读视图。
  • 当前读会生成一个最新版本的读视图。

读视图是基于下面几个字段实现的:

  • m_ids: 当前系统中活跃的事务ID集合,即未提交的事务。
  • min_trx_id: m_ids种最小的id
  • max_trx_id: 下一个要分配的事务ID。
  • creator_trx_id: 当前事务ID

读视图决定当前事务能读到哪个版本的数据,从表记录到undo log历史数据的版本链,依次匹配,满足哪个版本的匹配规则,就能读取到哪个版本的数据,一旦匹配成功就不在往下匹配。

数据可见性规则

  1. DB_TRX_ID = creator_trx_id 如果这个版本数据的事务ID等于当前事务ID,表示数据记录的最后一次操作的事务就是当前事务,当前读视图可以读到这个版本的数据。
  2. DB_TRX_ID < min_trx_id 如果这个版本数据的事务ID小于所有活跃事务ID,表示这个版本的数据不再被事务使用,即事务已提交,当前读视图可以读到这个版本的数据。
  3. DB_TRX_ID >= max_trx_id 如果这个版本数据的事务ID大于等于下一个要分配的事务ID,表示有新事务更新了这个版本的数据,这种情况下,当前读视图不可以读到这个版本的数据。
  4. min_trx_id <= DB_TRX_ID < max_trx_id 如果这个版本数据的事务ID在当前系统中活跃的事务ID集合(m_ids)里面,表示这个版本的数据被其他事务更新过,当前读视图不可以读到这个版本的数据。 如果这个版本数据的事务ID不在当前系统中活跃的事务ID集合(m_ids)里面,表示是在其他事务提交后创建的读视图,当前读视图可以读到这个版本的数据。

不同隔离级别下可见性分析

在不同的事务隔离级别下,生成读视图的规则不同:

  • READ COMMITTED(读已提交) :在事务中每一次执行快照读时都生成一个读视图,每个读视图中四个字段的值都是不同的。
  • REPEATABLE READ(可重复读):仅在事务中第一次执行快照读时生成读视图,后续复用这个读视图。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值