【MySQL】InnoDB存储引擎实现事务的原理及MVCC-实现原理

本文详细阐述了redolog如何确保事务持久性,undolog在事务原子性和MVCC中的作用,以及MVCC中的快照读、当前读、隐藏字段、版本链和readview等概念。讨论了不同隔离级别下MVCC的实现原理和脏读问题。
摘要由CSDN通过智能技术生成

在这里插入图片描述

redo log 实现了事务的持久性

如果没有redo log,可能出现脏页现象,导致从缓冲池中更改后加载到硬盘的过程中出现脏页,无法保证持久性。
redo log会记录内存结构中缓冲区中的增删改变化,即时出现脏页,redo log把变化加载到硬盘中,进行数据恢复,这样就保证了事务的持久性。

在这里插入图片描述

undo log 实现了事务的原子性

回滚日志,用于记录数据被修改前的信息 , 作用包含两个 : 提供回滚(保证事务的原子性) 和MVCC(多版本并发控制) 。

undo log和 redo log记录的物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的 update 记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。
undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment回滚段中,内部包含1024个undo log segment。

一、快照读

简单的 select 就是快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。

  • Read Committed:每次select,都生成一个快照读。
  • Repeatable Read:开启事务后第一个select语句才是快照读的地方。
  • Serializable:快照读会退化为当前读。

快照读通过 MVCC 避免了 幻读

幻读:当同一个查询在不同的时间产生不同的结果集时,事务中就会出现所谓的幻读问题。例如:如果 SELECT 执行了两次,但第二次返回了第一次没有返回的行,则改行就是 “幻读” 行。

二、当前读

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,比如 select … lock in share mode,select …for update、update、insert、delete 等除了普通的 select 都是一种当前读。

当前读 通过记录锁和间隙锁避免了 幻读

MVCC

全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。
在这里插入图片描述

  • 隐藏字段
    创建表时,MySQL会自动为当前表创建三个隐藏的字段。

    • DB_TRX_ID
      最近一次修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
    • DB_ROLL_PTR
      回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
    • DB_ROW_ID
      隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
  • undo log 版本链
    在这里插入图片描述
    不同事务对同一条记录 修改,会导致记录的undo log生成一条记录版本的链表,链表头部是最新的旧记录,链表尾部是最早的旧记录。

  • readview
    readview(读视图)是快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。

    • m_ids:当前活跃的事务(未提交)集合。
    • trx_id:当前记录的事务id
    • creator_trx_id:readview创建者的事务id
    • min_trx_id:最小事务id
    • max_trx_id:预分配事务id,最大事务id + 1
      在这里插入图片描述

不同的隔离级别,生成 ReadView 的时机不同:
READ COMMITTED:在事务中每一次执行快照读时生成 ReadView。
REPEATABLE READ:仅在事务中第一次执行快照读时生成 ReadView ,后续复用该 ReadView。

MVCC-实现原理

在这里插入图片描述

在RC隔离级别中,每次简单的select操作就会生成一个快照读对应的readview,readview 中记录了当前行的事务id等信息,undo log 中记录了当前行的版本链,保存了各个版本修改前的数据,根据版本链路访问规则,找到对应事务id的版本和数据,则就是 select操作实际访问到的数据。
在上图中,第一次查询 id=30 的记录时 creator_trx_id=5, 从 undo log 版本链中,找出符合右下图事务访问条件的行记录,对应事务2 已提交的数据。但是第二次查询 id=30 的记录时, 按照上述方法查到的结果是事务3 提交后对应的行记录,与第一次查询的结果不一致

在 READ COMMITTED 隔离级别下,解决了脏读,但是未解决不可重复读。

在这里插入图片描述
执行调用的过程同 RC。

  • 30
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值