Mysql-事务原理与MVCC

事务实现原理

在这里插入图片描述

Redo Log — 实现事务的持久性和一致性

   Redo Log:重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性;
  该日志文件由两部分组成:重做日志缓冲区(redo log buffer)、重做日志文件(redo log file),前者在内存中,后者在磁盘中。
  当事务提交后会把所有修改信息都存到改日志文件中,用于在刷新脏页到磁盘发生错误时,恢复数据用。

Redo Log 设计理念

  • 思考
      为什么在刷新脏页出错恢复数据时,不直接将Buffer Pool中的数据重新刷入磁盘,而是要通过RedoLog buffer来进行数据的再次刷入?

  • 答案
      ① 数据一致性:数据库事务可能包含多个操作,如若遇到数据库崩溃,可能造成部分脏页已经写入磁盘,而其他脏页由于崩溃导致丢失,如果直接将 Buffer Pool 中的数据重新刷入磁盘,那么在崩溃前已经写入到磁盘的脏页将无法回滚到崩溃前的状态,导致是数据不一致。通过重做日志Redo Log的应用,可以根据崩溃前记录的修改操作,重新应用这些操作来恢复所有脏页数据,确保数据一致性;
      ② 效率和性能:直接将 Buffer Pool 中的数据重新刷入磁盘存在性能问题:如果每次崩溃都将所有数据重新 刷入磁盘,会导致大量的磁盘随机IO操作,从而严重影响性能。而使用 Redo Log Buffer 可以将数据先写入到内存中,再通过批量刷写的方式将数据写入磁盘,这样可以提高整体性能和吞吐量;
      ③ 数据保护Redo Log Buffer 本身也是一种持久化存储的数据结构,即使系统崩溃,Redo Log Buffer 中的数据也能在恢复过程中被保护和使用。通过记录事务的修改操作,重做日志是数据库系统中的关键组建,可确保在恢复过程中的数据完整性和正确性。

Redo Log恢复数据步骤

  当数据库崩溃后重启,数据库系统将通过重做日志里执行崩溃前未完成的事务操作,以达到一致性。具体恢复步骤如下:
  ① 数据库重启后,系统会检查重做日志,读取日志中未提交的事务记录;
  ② 根据重做日志的记录,逐个重新执行未完成的事务操作,并将修改后的页数据写入Buffer Pool
  ③ 重做日志的记录在完成重做后会被标记为已提交,确保不会重复执行。

重做日志的可靠性如何保证

  1. 写入顺序:重做日志采用顺序写入的方式,将日志记录追加到日志文件的结尾,避免了随机磁盘IO,提高了写入效率,减少了数据损坏和丢失的风险;
  2. 日志缓冲:数据库会使用日志缓冲Log Buffer,将日志记录先写入缓冲,再批量写入磁盘,这样可以减少磁盘访问次数,降低数据丢失风险;
  3. 同步策略:数据库可以采用不同的同步策略来确保重做日志的数据持久性。常见的策略是将日志记录与对应的数据页同时刷写在磁盘上,即 “write-ahead logging”(WAL) 的方式。确保数据在写入磁盘前,相关的日志记录已经持久化到磁盘上,避免了数据的不一致;
  4. 冗余和备份:为防止重做日志的数据丢失,数据库系统常会进行冗余存储和定期备份。冗余存储可通过将重做日志数据存储在多个独立的物理设备上,如 磁盘阵列(RAID) 等方式实现。而备份则是将重做日志数据定期复制到其他介质,如磁盘或远程服务器,以便在主数据库故障时进行恢复。

“write-ahead logging”(WAL)策略

  1. 对数据库进行修改操作时,首先将修改操作写入重做日志中,以日志形式记录;
  2. 在将数据页写入 Buffer Pool 进行修改之前,系统将相关的日志记录持久化到日志文件中,通常采用顺序追加的方式写入;
  3. 接下来,系统将修改操作应用于 Buffer Pool 中对应的数据页,即在内存中进行修改;
  4. 修改数据页被写回磁盘时,数据库将会将相应修改操作一并写入磁盘,以保证数据库的一致性和持久性。
  5. 通过这种方式,重做日志可确保在数据写入磁盘前,相关的日志记录已经被持久化到磁盘上。而且,数据库奔溃时,可通过重做日志的内容重新执行修改操作,使数据库回滚到最后一个一致状态。

Undo Log — 实现事务的原子性

  Undo Log:回滚日志,用于记录数据被修改前的信息
  主要作用 :提供回滚和MVCC(多版本并发控制)

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

  • Undo Log销毁时机
      undo log 在执行事务执行时产生,事务提交时,一般情况下不会立即删除undo log,因为这些日志可能还用于MVCC。
      当insert的时候,产生的undo log 日志只在回滚时需要,在事务提交后可被立即删除;
      而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。

  • Undo Log存储
      undo log 采用段的方式进行管理和记录,存放在rollback segment回滚段中,内部包含1024个undo log segment

MVCC

   MVCC:多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为Mysql实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录的三个隐式字段、undo log日志、readView

MVCC基本概念

  • 当前读
      读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select … lock in share mode(共享锁),select …for update、update、insert、delete(排他锁)都是一种当前读。
  • 快照读
      简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读;
      Read Commited:每次select,都生成一个快照读;
      Repeatable Read:开启事务后第一个select语句才是快照读的地方,后续的所有select读取的都是这个快照;
      Serializable:快照读会退化为当前读。

MVCC实现原理

  • 记录中的隐藏字段
      如下图,表中存在三个隐式字段:DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID。
    在这里插入图片描述
      DB_TRX_ID:最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID;
      DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本;
      DB_ROW_ID:隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
  • undo log版本链
    在这里插入图片描述
      不同事务或相同事务对同一条记录进行修改,会导致undo log生成一条记录版本链表,链表的头部是最新的旧记录,链表的尾部是最早的旧记录。
  • ReadView
      ReadView(读视图):是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。
      ReadView包含了下面四个核心字段:
    在这里插入图片描述
    版本链数据访问规则
    在这里插入图片描述
    不同的隔离级别,生成ReadView的时机不同:
      ① Read Committed:在事务中每一次执行快照读时生成ReadView;
      ② Repeatable Read:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

RC / RR 隔离级级别下的 ReadView

  • RC(Read Committed) 隔离级别下的Readview
    在这里插入图片描述
  • RR(Repeatable Read)级别下的ReadView
    RR级别下,仅在事务第一次执行快照读时生成ReadView,后续复用ReadView。其ReadView的提取方式与RC隔离级别下的提取方式一致。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值