首页 > 数据库 >MySQL 事务的两阶段提交

MySQL 事务的两阶段提交

时间:2023-06-10 17:34:01浏览次数:47  
标签:binlog 事务 log MLOG 提交 MySQL 日志 redo

 

什么是事务

事务是数据库中一组原子性的操作,要么全部成功,要么全部失败。事务具有四个特性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),简称 ACID。

在 MySQL 中,我们可以使用 begin 或 start transaction 命令开启一个事务,使用 commit 命令提交一个事务,或者使用 rollback 命令回滚一个事务。例如:

begin;
update account set balance = balance - 100 where id = 1;
update account set balance = balance + 100 where id = 2;
commit;

上面的例子是一个转账的场景,我们将 id 为 1 的账户的余额减少 100,将 id 为 2 的账户的余额增加 100。这两个操作要么同时成功,要么同时失败,不能出现中间状态。

MySQL 中的日志

为了保证事务的 ACID 特性,MySQL 需要记录一些日志来辅助事务的执行和恢复。MySQL 中主要有两种日志:redo log 和 binlog。

redo log 是 InnoDB 存储引擎特有的日志,用于记录数据页的物理修改,保证事务的持久性和原子性。redo log 是循环写入的,由两部分组成:一块固定大小的内存区域(redo log buffer)和一组固定大小的磁盘文件(redo log file)。当事务对数据进行修改时,会先将修改记录到 redo log buffer 中,然后在适当的时机将其刷新到 redo log file 中。这样即使数据库发生异常重启,也可以根据 redo log 恢复数据。

binlog 是 MySQL Server 层的日志,用于记录 SQL 语句的逻辑修改,保证事务的一致性。binlog 是追加写入的,由一个 binlog 文件序列和一个索引文件组成。当事务提交时,会将 SQL 语句记录到 binlog 中。binlog 主要用于数据备份、恢复和主从复制。

为什么需要两阶段提交

如果只有 redo log 或者只有 binlog,那么事务就不需要两阶段提交。但是如果同时使用了 redo log 和 binlog,那么就需要保证这两种日志之间的一致性。否则,在数据库发生异常重启或者主从切换时,可能会出现数据不一致的情况。

例如,假设我们有一个事务 T,它修改了两行数据 A 和 B,并且同时开启了 redo log 和 binlog。如果我们先写 redo log 再写 binlog,并且在写完 redo log 后数据库发生了宕机,那么在重启后,根据 redo log 我们可以恢复 A 和 B 的修改,但是 binlog 中没有记录 T 的信息,导致备份或者从库中没有 T 的修改。反之,如果我们先写 binlog 再写 redo log,并且在写完 binlog 后数据库发生了宕机,那么在重启后,根据 redo log 我们无法恢复 A 和 B 的修改,但是 binlog 中有记录 T 的信息,导致备份或者从库中有 T 的修改。

为了避免这种情况,MySQL 引入了两阶段提交的机制。两阶段提交就是将一个事务分成两个阶段来提交:prepare 阶段和 commit 阶段。在 prepare 阶段,事务会先写 redo log 并将其标记为 prepare 状态,然后写 binlog;在 commit 阶段,事务会将 redo log 标记为 commit 状态,并将 binlog 落盘。这样,无论数据库在哪个时刻发生宕机,都可以根据 redo log 和 binlog 的状态来判断事务是否提交,并保证数据的一致性。

两阶段提交的流程

下面我们通过一个例子来具体看看两阶段提交的流程。假设我们有一个事务 T,它执行了以下 SQL 语句:

begin;
update account set balance = balance - 100 where id = 1;
update account set balance = balance + 100 where id = 2;
commit;

这个事务的两阶段提交的流程如下:

  1. 在 prepare 阶段,事务 T 会先将两条 update 语句的修改记录到 redo log buffer 中,然后将 redo log buffer 刷新到 redo log file 中,并将其标记为 prepare 状态。此时,redo log file 中会有类似以下的内容:

    LSN | XID | TYPE | DATA
    ----|-----|------|-----
    100 | T   | MLOG_UNDO_HDR | ...
    101 | T   | MLOG_UNDO_INSERT | ...
    102 | T   | MLOG_UNDO_INSERT | ...
    103 | T   | MLOG_2PC_PREPARE | ...

    其中,LSN 是日志序列号,XID 是事务 ID,TYPE 是日志类型,DATA 是日志内容。MLOG_UNDO_HDR 表示 undo 日志的头部信息,MLOG_UNDO_INSERT 表示 undo 日志的插入操作,MLOG_2PC_PREPARE 表示两阶段提交的 prepare 操作。

  2. 然后,事务 T 会将两条 update 语句记录到 binlog 中,并将 binlog 写入到 binlog 文件中。此时,binlog 文件中会有类似以下的内容:

    LOG_POS | XID | TYPE | DATA
    --------|-----|------|-----
    200     | T   | QUERY_EVENT | begin
    201     | T   | QUERY_EVENT | update account set balance = balance - 100 where id = 1
    202     | T   | QUERY_EVENT | update account set balance = balance + 100 where id = 2

    其中,LOG_POS 是日志位置,XID 是事务 ID,TYPE 是日志类型,DATA 是日志内容。QUERY_EVENT 表示 SQL 语句的事件。

  3. 在 commit 阶段,事务 T 会将 redo log 的状态从 prepare 改为 commit,并将 binlog 落盘。此时,redo log file 中会有类似以下的内容:

    LSN | XID | TYPE | DATA
    ----|-----|------|-----
    100 | T   | MLOG_UNDO_HDR | ...
    101 | T   | MLOG_UNDO_INSERT | ...
    102 | T   | MLOG_UNDO_INSERT | ...
    103 | T   | MLOG_2PC_PREPARE | ...
    104 | T   | MLOG_2PC_COMMIT |
  4. 最后,事务 T 完成提交,并释放锁资源。

总结

MySQL 的两阶段提交是为了保证同时使用 redo log 和 binlog 的情况下,数据的一致性。两阶段提交将一个事务分成 prepare 阶段和 commit 阶段,在 prepare 阶段写 redo log 和 binlog,在 commit 阶段修改 redo log 的状态并落盘 binlog。这样可以避免数据库发生异常重启或者主从切换时出现数据不一致的情况。

标签:binlog,事务,log,MLOG,提交,MySQL,日志,redo
From: https://www.cnblogs.com/shoshana-kong/p/17471621.html

相关文章

  • mysql创建表时,字段的类型(转载)
    常用的字段类型大致可以分为数值类型、字符串类型、日期时间类型三大类,下面我们按照分类依次来介绍下。1、数值类型数值类型大类又可以分为整型、浮点型、定点型三小类。  2、字符串类型字符串类型也经常用到,常用的几个类型如下表: 其中char和varchar是最常用到......
  • mysql 主从复制 原理
     mysql主从复制定义mysql主从复制是一种数据同步的技术,它可以让一个或多个从数据库(slave)复制主数据库(master)的数据变化。这样可以提高数据库的可用性、性能和扩展性,也可以实现读写分离和数据备份。mysql主从复制原理mysql主从复制的原理是基于二进制日志(binlog)的,主数据库......
  • mysql MVCC 原理
    MVCC的定义MVCC,即多版本并发控制,是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。MVCC的目的是为了提高数据库的并发性能,用更好的方式去处理读写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。MVCC的目的在MySQL中,InnoDB......
  • 本地mysql服务无法启动 解决方案
    问题引入:在我启动SQLyog时,无法连接mysql,检查MYSQL服务,并无法手动启动,由此一下是解决步骤。首先,以管理员身份打开cmd。进入到mysql的bin目录,这里需要各位去文件找找路径;在bin下,删除mysqld的所有内容;​ mysqld--remove成功:Servicesuccessfullyremoved.......
  • Python 3.x对MySQL数据库的常用操作
    首先安装MySQL,然后使用pipinstallpymysql安装扩展库,最后执行下面的代码。运行结果:公众号“Python小屋”......
  • MySQL数据库安全评估工具
    MySQL数据库安全评估工具MySQLDatabaseSecurityAssessmentTool   MySAT执行多项测试以分析数据库配置和安全策略。MySAT可以帮助评估并因此提高MySQL数据库的安全性。MySAT是一个简单的SQL脚本,它易于理解,易于维护。MySAT的结果是一份HTML格式的报告。MySQL数据库安全评估......
  • 【后端面经-数据库】MySQL的存储引擎简介
    目录MySQL的存储引擎0.存储引擎的查看和修改1.MyISAM2.InnoDB3.MEMORY4.MERGE5.总结6.参考博客MySQL的存储引擎mysql主要有四类存储引擎,目前主要使用InnoDB作为存储引擎。0.存储引擎的查看和修改查看当前数据库的默认存储引擎showvariableslike'default_storage_e......
  • SpringBoot+Mysql+IDEA开发的社区医疗综合服务平台
    基于springboot的社区养老医疗综合服务平台项目介绍......
  • 数据库事务隔离级别
    标准隔离级别读未提交、读已提交、可重复读、串行化串行化对事务中所有读写的数据加上读锁、写锁、范围锁。所以冲突的事务必须同步执行。//console1starttransaction;select*fromtransaction_testwhere`key`=1;updatetransaction_testsetname='newTest'where......
  • 2023-06-09:什么是Redis事务?原理是什么?
    2023-06-09:什么是Redis事务?原理是什么?答案2023-06-09:Redis中的事务是以一组命令的形式出现的,这些命令被认为是最小的执行单位。事务可以保证在一个单独独立的隔离操作中执行所有命令,而且所有命令都会按照指定的顺序经过序列化后被执行。在服务端执行事务的过程中,不受其他客户端发送......