InnoDB存储引擎对MVCC实现

MVCC(多版本并控制)

概念:MVCC 是一种并发控制机制。

作用:多个并发事务同时读写数据库时保持数据的一致性和隔离性

实现:在每个数据行上维护多个版本的数据来实现的。当一个事务要对数据库中的数据进行修改时,MVCC 会为该事务创建一个数据快照,而不是直接修改实际的数据行。

1、读操作

事务执行读操作的时候,会使用快照读取,事务不会读取其他事务尚未提交的修改。

2、写操作

事务执行写操作的时候,会生成一个新的数据版本,并将修改后的数据写入数据库。(原始版本的数据仍然存在,供其他事务使用快照读取)

3、事务提交和回滚
  • 事务提交后,所做的修改将成为数据库的最新版本,并且对其他事务可见。
  • 事务回滚时,所做的修改将被撤销,对其他事务不可见。
4、版本回收

防止数据库中的版本无限增长,MVCC会定期进行版本回收,从而释放空间。

总结:MVCC创建多个版本 和 使用快照读取来实现并发控制。读操作使用旧数据版本的快照,写操作创建新版本,并确保原始版本仍可以使用 。

一致性非锁定读

实现:加一个版本号 / 时间戳字段,查询时,将当前可见的版本号与对应记录的版本号进行对比,如果记录的版本号小于可见版本,则表示该记录可见。

多版本控制就是读非锁定读的实现。如果读取的行正在执行DELETEUPDATE操作,这时读取操作不会去等待行上锁的释放,InnoDB存储引擎会去读取行的快照(快照读)

锁定读

在锁定读下,读取的数据是数据的最新版本,这种读也被称为当前读,同时,锁定读会对读取到的记录加锁。

存在问题:如果是当前读,每次读取的都是最新数据,两次查询中间,如果有其他事务插入数据,就会导致幻读,所以,InnoDB在实现可重复读时,如果执行的是当前读,则会对读取的记录使用Next-key Lock,来防止其他事务在间隙间插入数据。

InnoDB 对MVCC的实现

在内部,InnoDB存储引擎为每行数据添加了三个隐藏字段

  • DB_TRX_ID(6字节):表示最后一次插入或更新该行的事务 id。此外,delete 操作在内部被视为更新,只不过会在记录头 Record header 中的 deleted_flag 字段将其标记为已删除
  • DB_ROLL_PTR(7字节) 回滚指针,指向该行的 undo log 。如果该行未被更新,则为空
  • DB_ROW_ID(6字节):如果没有设置主键且该表没有唯一非空索引时,InnoDB 会使用该 id 来生成聚簇索引

Undo-log(撤销日志)

作用:

  1. 事务回滚:事务回滚时用于将数据恢复到修改前的样子
  2. MVCC:当读取记录时,若该记录被其他事务占用或当前版本对该事务不可见,则可以通过undo log读取之前的版本数据,以此实现非锁定读

RC 和 RR隔离级别下MVCC的差异

在事务隔离级别 RCRR (InnoDB 存储引擎的默认事务隔离级别)下,InnoDB 存储引擎使用 MVCC(非锁定一致性读),但它们生成 Read View 的时机却不同

  • 在 RC 隔离级别下的 每次select 查询前都生成一个Read View (m_ids 列表)
  • 在 RR 隔离级别下只在事务开始后 第一次select 数据前生成一个Read View(m_ids 列表)

MVCC + Next-key Lock 防止幻读

InnoDB存储引擎在 RR 级别下通过 MVCCNext-key Lock 来解决幻读问题:

1、执行普通select,此时会以MVCC快照读的方式读取数据

在快照读的情况下,RR 隔离级别只会在事务开启后的第一次查询生成 Read View ,并使用至事务提交。所以在生成 Read View 之后其它事务所做的更新、插入记录版本对当前事务并不可见,实现了可重复读和防止快照读下的 "幻读"

2、执行 select...for update/lock in share mode、insert、update、delete 等当前读

在当前读下,读取的都是最新的数据,如果其它事务有插入新的记录,并且刚好在当前事务查询范围内,就会产生幻读!InnoDB 使用 Next-key Lock 来防止这种情况。当执行当前读时,会锁定读取到的记录的同时,锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读

相关推荐
cui_win4 分钟前
MySQL 压测实战:sysbench 从入门到精通
数据库·mysql·压测·sysbench
Selegant6 分钟前
Docker 搭建 MySQL 主从服务实战操作详解
mysql·docker·容器
qq_348231851 小时前
MySQL 与 PostgreSQL PL/pgSQL 的对比详解
数据库·mysql·postgresql
cui_win2 小时前
Prometheus实战教程 - mysql监控
mysql·prometheus·压测
wsx_iot2 小时前
mysql的快照读和当前读
数据库·mysql
梁萌2 小时前
MySQL分区表使用保姆级教程
数据库·mysql·优化·分区表·分区·partitions
Logic1013 小时前
《数据库运维》 郭文明 实验4 数据库备份与恢复实验核心操作与思路解析
运维·数据库·sql·mysql·学习笔记·形考作业·国家开放大学
hssfscv3 小时前
Mysql学习笔记——多表查询
笔记·学习·mysql
MC皮蛋侠客4 小时前
MySQL数据库迁移脚本及使用说明
数据库·mysql
soft20015254 小时前
《Rocky Linux 9.6 部署 MySQL 8.0 生产手册(含错误处理)》
linux·mysql·adb