MySQL的innodb引擎是如何实现MVCC的

本文介绍InnoDB存储引擎如何使用多版本并发控制(MVCC)实现事务隔离性,探讨B+Tree与Hash索引的数据结构特点及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

索引的数据结构有B+treee索引和hash索引:B+treee索引是innodb引擎默认使用的数据结构,它通过一定的算法,将mysql表中数据分磁盘存放,少量的磁盘读取即可做到大量数据的遍历;Hash索引根据hash算法将数据,精确的存放,来查找某个数据的时候,根据相同的算法一次就能找到,等值查询,效率非常高,但hash索引只能等值查询,而且容易发生hash碰撞。

innodb会为每一行添加两个字段,分别表示该行创建的版本删除的版本,填入的是事务的版本号,这个版本号随着事务的创建不断递增。在repeated read的隔离级别(事务的隔离级别请看这篇文章)下,具体各种数据库操作的实现:

  • select:满足以下两个条件innodb会返回该行数据:
    • 该行的创建版本号小于等于当前版本号,用于保证在select操作之前所有的操作已经执行落地
    • 该行的删除版本号大于当前版本或者为空。删除版本号大于当前版本意味着有一个并发事务将该行删除了
  • insert:将新插入的行的创建版本号设置为当前系统的版本号。
  • delete:将要删除的行的删除版本号设置为当前系统的版本号。
  • update:不执行原地update,而是转换成insert + delete。将旧行的删除版本号设置为当前版本号,并将新行insert同时设置创建版本号为当前版本号

其中,写操作(insert、delete和update)执行时,需要将系统版本号递增

​ 由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge

通过MVCC很好的实现了事务的隔离性,可以达到repeated read级别,要实现serializable还必须加锁。

 

MVCC的实现

  1. 为了实现MVCC,innodb对每一行都加上两个隐含的列,其中一列存储行被更新的时间,另外一列存储行被删除的时间。但是innodb存储的并不是绝对的时间,而是与时间对应的数据库系统的版本号。(保存这两个额外系统版本号使大多数读操作可以不加锁)

  2. 每当一个事务开始的时候,innodb都会给这个事务分配一个递增的版本号。所以版本号也可以被认为是事务号。

  3. 对于每一个查询语句,innodb都会把这个查询语句的版本号同查询遇到的行的版本号进行对比,然后结合不同的事务等级来决定是否返回该行。

select语句实现

Innodb只查找版本号早于当前事务版本的数据号(包括等于)。这样可以确保事务读取的行要么是事务开始前已经存在的,要么是事务自身插入或修改的。

行的删除版本号,要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行在事务开始之前未被删除。

insert语句实现

Innodb为新插入的每一行保存当前系统版本号作为行版本号。

update语句实现

Innodb为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号为原来的行的删除标识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值