MySQL多版本并发控制MVCC

I will always be here for you

目录

一,什么是 MVCC

二,MVCC 的具体工作流程

三,MVCC 在不同隔离级别下的读取规则

四,MVCC 如何解决幻读

五,next-key lock机制的具体实现

六,next-key lock 机制的优化规则和特殊情况的具体例子

 

一,什么是 MVCC

  • MVCC 是多版本并发控制的缩写,是 MySQL InnoDB 存储引擎实现事务隔离级别和回滚的重要功能。
  • MVCC 的主要思想是记录数据的版本变化,通过选择不同数据的版本,对用户呈现一致的结果。
  • MVCC 主要是通过行记录中的隐藏字段(row_id,trx_id,roll_pointer),undo log(版本链),ReadView(一致性读视图)来实现的。

二,MVCC 的具体工作流程

  1. 事务开始时,从数据库获取一个自增的事务 ID,作为事务版本号,可以用来判断事务的执行先后顺序。
  2. 事务对数据进行修改时,不直接覆盖原始数据,而是生成一个新的数据版本,并将新数据的 trx_id 设置为当前事务ID,同时将原始数据的 row_id 设置为新数据的地址,形成一个版本链。
  3. 事务对数据进行读取时,根据隔离级别和一致性读视图,选择合适的数据版本进行读取。一致性读视图是一个数组,记录了当前活跃事务的 ID 和系统最大事务 ID。
  4. 事务结束时,根据事务的执行结果,提交或回滚事务,并释放占用的资源。

三,MVCC 在不同隔离级别下的读取规则

  MVCC只在**读已提交(RC)可重复读(RR)**隔离级别下生效,因为它主要是用来解决脏读和不可重复读的问题。

  在RC隔离级别下,一个事务的每一次查询都会获取一个新的 ReadView,这样就可能导致同一个事务里,两次相同的查询返回了不同的结果,也就是出现了不可重复读的问题。

  在RR隔离级别下,一个事务只在第一次查询时获取一个 ReadView,并且在整个事务中保持不变,这样就可以保证同一个事务里,两次相同的查询返回了相同的结果,也就是避免了不可重复读的问题。

四,MVCC 如何解决幻读

  幻读是指一个事务在查询某个范围的数据时,发现其他事务插入了新的数据,导致两次查询的结果不一致的现象。

  MVCC 解决幻读的问题主要分为两种情况:快照读当前读

  快照读是指普通的 select 语句,它不会加锁,而是通过 ReadView 来选择合适的数据版本进行读取。在 RR 隔离级别下,快照读可以避免幻读,因为一个事务看到的数据一直跟它启动时看到的数据是一致的,即使中途有其他事务插入了新的数据,也查询不出来。

  当前读是指 select…for update 等语句,它会加锁,而且总是读取最新的数据版本。为了解决当前读的幻读问题,MySQL 引入了 next-key lock 机制,它是记录锁和间隙锁的结合。记录锁是对一条记录加锁,间隙锁是对两条记录之间的空隙加锁。这样就可以防止其他事务在锁定范围内插入新的数据,从而避免幻读。

五,next-key lock机制的具体实现

  next-key lock 机制是指对一条记录以及这条记录前面的间隙加锁,形成一个前开后闭的区间。例如,如果有一个索引列的值为1,2,4,5,那么 next-key lock 就会锁住以下四个区间:(-∞, 1],(1, 2],(2, 4],(4, 5]。

  next-key lock 机制的作用是防止其他事务在锁定范围内插入新的数据,从而避免幻读。例如,如果一个事务对索引列值为2的记录加了 next-key lock,那么其他事务就不能在(1, 2]和(2, 4]这两个区间内插入新的数据。

  next-key lock机制有一些优化规则和特殊情况,例如:

  • 如果索引是唯一索引,并且查询条件是等值查询,那么 next-key lock 会退化为行锁。
  • 如果查询条件是范围查询,并且扫描到最左或最右边界,那么 next-key lock 会只锁住一个区间。
  • 如果扫描到不存在的记录,那么 next-key lock 会只锁住一个空间隙。

六,next-key lock 机制的优化规则和特殊情况的具体例子

假设有一个表 t,它有一个唯一索引 id 和一个非唯一索引 name,表中有以下数据:

id name
1 Alice
2 Bob
3 Carol
4 David

 

 

 

 

posted @ 2023-05-23 17:54  ZZKZS  阅读(4)  评论(0编辑  收藏  举报
/*鼠标跟随效果*/