MySQL--InnoDB的一次更新事务实现流程与二阶段提交

文章目录

        • InnoDB更新事务流程
          • 涉及内容
          • 完整的更新流程步骤
        • 二阶段提交
          • 二阶段提交的步骤
          • 为什么需要二阶段提交
          • 二阶段提交如何保证一致性

InnoDB更新事务流程
涉及内容
  • 一次InnoDB的事务更新操作涉及Buffer Pool,BinLog,RedoLog,UndoLog和物理磁盘。

Buffer Pool:

  • Buffer Pool是InnoDB引入的中间层:内存上的一块连续空间,用来缓存数据页,每个数据页的大小为16KB。它的存在是为了提高SQL的读写性能,避免每次查询和修改都直接与磁盘进行交互。于是,每次读取数据的时候,InnoDB会先检查Buffer Pool中是否存在该数据,存在则直接从内存中取,若不存在,再去磁盘中获取,获取后将该数据所在的页复制一份存入Buffer Pool。这样做,避免了频繁的磁盘读取,从而可以提高查询性能。

BinLog:

  • BinLog是MySQL用来记录所有DDL和DML语句的二进制文件,用于数据库的数据备份,数据复制等操作。为了支持高并发,数据库有时会进行读写分离,主库的数据通过BinLog日志来同步复制给从库。

RedoLog:

  • RedoLog是MySQL用于实现数据持久化和崩溃恢复的一种机制,在事务执行过程中,MySQL会将事务做的改动记录到RedoLog中。当系统发生崩溃或数据异常时,RedoLog可以进行数据库重启后的恢复工作,保证了数据库事务的持久性。

UndoLog:

  • UndoLog用于事务的回滚操作,当一个事务执行过程中,MySQL会将修改前的数据记录到UndoLog中,如果事务发生了异常需要回滚,则从UndoLog中找到对应的记录执行,以撤销事务的操作,确保事务的原子性和一致性。此外,UndoLog还支持MVCC(多版本并发控制)机制,用于在并发事务执行时,提供一定的隔离性。
完整的更新流程步骤
  1. 在Buffer Pool中读取数据,若该数据不在Buffer Pool中,则从磁盘读取该数据所在的数据页放入Buffer Pool中。
  2. 记录UndoLog,在数据修改前,InnoDB会在UndoLog中记录修改前的数据。UndoLog最开始写在内存中,由后台线程定时刷入磁盘。
  3. 在Buffer Pool中执行Update语句,更新数据。然后将更新后的数据页状态设置为脏页(dirty page),表示该页已修改但未刷入磁盘。
  4. 记录RedoLog,InnoLog将修改操作写入RedoLog buffer pool中,此时为二阶段提交的prepare阶段。
  5. 记录BinLog,在提交过程中,InnoDB会将事务提交信息记录到BinLog中。BinLog中记录的信息包括:事务开始时间,数据库名,表名,事务ID,SQL语句等。后续通过Binlog进行主从复制。将BinLog写入磁盘中,完成后将RedoLog也写入磁盘。此为二阶段提交的commit阶段。
  6. 写入磁盘,在提交过程后,InnoDB会将Buffer Pool里的脏页写入磁盘,以保证数据库的持久性。这个写入过程是后台线程异步执行的,具有延迟性。

注意:在BinLog和RedoLog写入的时候,是分了两个阶段,以二阶段提交的方式来保证一致性。

二阶段提交
二阶段提交的步骤
  • prepare阶段
    • 这个阶段SQL成功执行并生成RedoLog,并处于准备阶段。
  • commit阶段
    • BinLog持久化:通过write()方法将BinLog写入文件缓冲区,再通过fsync()将文件缓存区中的BinLog写入磁盘。
    • RedoLog写入磁盘。
为什么需要二阶段提交
  • 采用二阶段可以保证BinLog日志和RedoLog日志的一致性。如果二者的一致性不能保证,那么主从库的数据就会出现不一致。
  • 如果RedoLog写入成功,而BinLog还未写入成功,此时主库崩了,那么重启后,主库可以通过RedoLog恢复数据,但是BinLog日志的数据没写成功,那么主从同步后,从库便缺少了相关的数据。
  • 如果BinLog写入成功,而RedoLog还未写入成功,此时主库崩了,那么重启后,主库可以无法RedoLog恢复丢失的数据,仍是事务执行前的状态,但是BinLog日志的数据已经写成功,那么主从同步后,从库会得到事务执行后的数据。
二阶段提交如何保证一致性
  • 若在prepare阶段数据库崩溃了,此时RedoLog已经写完,状态在prepare阶段,而BinLog没有成功写入,那么重启后根据RedoLog记录的事务id将对应事务进行回滚。
  • 若RedoLog在prepare阶段,而BinLog已经写入成功的时候数据库崩溃了,则重启后,若事务id对应的BinLog已经写入磁盘了,则即使RedoLog还没有commit,MySQL也要提交该事务。
  • 通过二阶段提交,保证了RedoLog和BinLog的一致性。

你可能感兴趣的:(mysql,数据库)