MYSQL的MVCC详解

前言

从第一次认识mvcc到今天终于搞懂mvcc大概过了两个月

之前一直觉得很复杂,但搞明白之后开始想不通自己之前为什么搞不懂

回顾

讲到mvcc,那就要先回顾一下数据库事务的四大特性

  • 原子性Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  • 一致性Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
  • 隔离性Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  • 持久性Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

接着自然而然发问:如何保证这四大特性?

原子性:undo log保证

持久性:redo log保证

隔离性:mvcc

一致性:满足了原子性、持久性、隔离性,就能够保证一致性

好,那接下来就来看mvcc

什么是MVCC

MVCC(Multi Version Concurrency Control),中文名是多版本并发控制,简单来说就是通过维护数据历史版本,从而解决并发访问情况下的读一致性问题。

理解mvcc之前,先要理解几个概念

版本链

对于 InnoDB 存储引擎,每一行记录都有两个隐藏列

  1. DB_TRX_ID:全称为 Database Transaction ID。这是一个在 InnoDB 存储引擎中用于标识事务的唯一标识符。每个事务都有一个唯一的 DB_TRX_ID,用于区分不同的事务。这个标识符可以用于识别事务的开始和结束,并跟踪事务的状态。

  2. DB_ROLL_PTR:全称为 Database Rollback Pointer。这是一个指向 InnoDB 存储引擎中事务回滚段(rollback segment)的指针。在事务执行期间,将对数据库进行修改的操作记录到事务日志中。DB_ROLL_PTR指向了这些修改的回滚段,以便在需要时进行回滚操作,确保数据库的一致性和持久性。

简单来说,DB_TRX_ID相当于事务id,它是按事务发起顺序自增的;DB_ROLL_PTR相当于指针,指向的是这行记录的前一个状态。由此我们知道,mvcc中的每一条记录都相当于一个链表

ReadView

在innoDB中,Read View 负责管理事务在执行期间看到的数据库快照(snapshot),以确保事务在执行过程中看到一致性的数据视图。

简单来说,每一条事务发起的时候,会生成一个ReadView,这条ReadView中包括以下四个信息

  • m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的事务 id 列表。
  • min_trx_id :表示在生成 ReadView 时当前系统中活跃的读写事务中最小的 事务 id ,也就是 m_ids 中的最小值。
  • max_trx_id :表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。
  • creator_trx_id :表示生成该 ReadView 的事务的 事务 id

那么,有了这些记录,就可以知道当前数据库中的某些数据是不是自己应该读到的了,如果当前数据是自己不该看到的,那就沿着链表往上找,知道找到自己应该看到的

规则如下:

  • 如果被访问版本的 DB_TRX_ID 属性值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。
  • 如果被访问版本的 DB_TRX_ID 属性值小于 ReadView 中的 min_trx_id 值,表明生成该版本的事务在当前事务生成 ReadView 前已经提交,所以该版本可以被当前事务访问。
  • 如果被访问版本的 DB_TRX_ID 属性值大于 ReadView 中的 max_trx_id 值,表明生成该版本的事务在当前事务生成 ReadView 后才开启,所以该版本不可以被当前事务访问。
  • 如果被访问版本的 DB_TRX_ID 属性值在 ReadView 的 min_trx_id 和 max_trx_id 之间,那就需要判断一下 trx_id 属性值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。
注意

事务在开始时分配一个唯一的事务 ID,并且在执行期间持有这个事务 ID。当事务提交时,它的事务 ID 就会在数据库中标记为已提交状态,以表示该事务已经完成。而如果事务回滚,那么相应的事务 ID 就会被标记为回滚状态。

那么看到这里,整个mvcc大概就是这么一个机制,其实也不难

四个隔离机制如何实现

读未提交:不加任何锁,可以读取mvcc中未提交的事务

读已提交:加读锁(记录锁),只能读取mvcc中已提交的事务

可重复读:前两者都是在每一次操作的时候获得当前的readview,而可重复读仅在事务开始的时候获取readview,整个事务共用这个readview

串行化:加读写锁(间隙锁和临键锁)

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值