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

MySQL 事务的两阶段提交--转

时间:2024-03-30 15:24:09浏览次数:19  
标签:binlog 事务 log -- 提交 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 的状态来判断事务是否提交,并保证数据的一致性。

两阶段提交的流程

 

MySQL采用了如下的二阶段提交流程:

  1. 在准备阶段,MySQL先将数据修改写入redo log,并将其标记为prepare状态,表示事务还未提交。然后将对应的SQL语句写入bin log。
  2. 在提交阶段,MySQL将redo log标记为commit状态,表示事务已经提交。然后根据sync_binlog参数的设置,决定是否将bin log刷入磁盘。

 

通过这样的流程,MySQL可以保证在任何时刻,redo log和bin log都是逻辑上一致的。如果MySQL发生崩溃,可以根据redo log恢复数据页的状态,也可以根据bin log恢复SQL语句的执行。

 

 

下面是一个简单的示例:

假设我们有一个表test_backup如下:

CREATE TABLE `test_backup` (
  `id` int (11) NOT NULL AUTO_INCREMENT,
  `name` varchar (255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后我们执行以下语句:

insert into test_backup values (1,'tom');
insert into test_backup values (2,'jerry');
insert into test_backup values (1,'herry');

这时候,MySQL会按照以下步骤进行二阶段提交:

  1. 将第一条插入语句写入redo log,并标记为prepare状态。
  2. 将第一条插入语句写入bin log。
  3. 将redo log标记为commit状态。
  4. 如果sync_binlog=1,则将bin log刷入磁盘。
  5. 重复以上步骤,直到所有插入语句都完成。

如果在这个过程中发生了崩溃,比如在第三步之前,那么MySQL重启后会根据redo log发现有一个prepare状态的事务,然后会去查找bin log中是否有对应的SQL语句。如果有,则说明该事务已经写入了bin log,可以提交;如果没有,则说明该事务还没有写入bin log,需要回滚。这样就可以保证数据的一致性。

总结

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

标签:binlog,事务,log,--,提交,MySQL,redo
From: https://www.cnblogs.com/hsjz-xinyuan/p/18105534

相关文章

  • 线性回归从零开始(麻雀虽小五脏俱全)
    目录构造数据集初始化模型参数定义模型定义损失函数定义优化算法训练过程线性回归是一个很好能理解深度学习的模型,麻雀虽小五脏俱全。构造数据集defsynthetic_data(w,b,num_examples):X=torch.normal(0,1,(num_examples,len(w)))y=torch.matmul(X,w)+by......
  • JoinPoint 常用的方法
    Object[]getArgs:返回目标方法的参数SignaturegetSignature:返回目标方法的签名ObjectgetTarget:返回被织入增强处理的目标对象ObjectgetThis:返回AOP框架为目标对象生成的代理对象*JoinPoint对象用于获取切面对象上下文信息,Aop将连接点的上下文信息封装为JoinPoint对象......
  • python str.split和rsplit笔记
    点击查看代码"""rsplit和split方法演示str.split(sep=None,maxsplit=-1)str.rsplit(sep=None,maxsplit=-1)"""#不指定sep或sep为None,拆分空字符串或只包含空格的字符串,返回为[](空列表)#1.空字符串str_1=''li_1_1=str_1.split()li_1_2=str_1.split(sep=None......
  • 渗透项目1-GoldenEye
    靶机地址:https://www.vulnhub.com/entry/goldeneye-1,240/靶机难度:中等(CTF)目标:得到root权限&找到flag.txt信息收集收集目标iparp-scan-l(收集本地网络中的活跃主机的IP地址和MAC地址。)kaliarp-scan网络扫描工具扫描局域网ip地址-阿里云开发者社区(aliyun.com)......
  • Rust简易入门(一)
    Rust!Rust!Rust!变量与不可变性在Rust中,变量使用let关键字进行声明Rust支持类型推导,也可以显示指定变量类型变量名采用蛇形命名法,枚举结构体采用帕斯卡命名法,没有使用的变量采用前置下划线_以消除警告强制类型转换关键词as打印变量println!("val:{}",x);print......
  • 存储器
    存储器分为寄存器Cache(高速缓冲存储器)主存储器辅存储器从下到上,速度越来越快,容量越来越小,成本越来越高 存储器的读取方式存取方式读/写装置数据块标志访问特性代表顺序存取共享读/写装置无特定线性顺序磁带直接存取......
  • openGauss每日一练(全文检索)
    openGauss每日一练(全文检索)本文出处:https://www.modb.pro/db/224179学习目标学习openGauss全文检索openGauss提供了两种数据类型用于支持全文检索。tsvector类型表示为文本搜索优化的文件格式,tsquery类型表示文本查询课后作业1.用tsvector@@tsquery和tsquery@@......
  • P9732 [CEOI2023] Trade
    洛谷传送门LOJ传送门考虑第一问,设一个区间的价值\(g(l,r)\)为\(f(l,r)-a_r+a_{l-1}\),其中\(a_i=\sum\limits_{j=1}^ic_j\),\(f(l,r)\)为\([l,r]\)中最大的\(k\)个\(b_i\)的和,设\(p_i\)为以\(i\)为右端点,区间价值最大的左端点,那么\(p_i\)满足决......
  • 洛谷题单指南-图的基本应用-P2853 [USACO06DEC] Cow Picnic S
    原题链接:https://www.luogu.com.cn/problem/P2853题意解读:找到所有奶牛都可以到达的牧场,就是要从奶牛所在位置开始遍历,求所有奶牛能重合的点的个数。解题思路:直接从从牛奶所在位置进行DFS,记录每个位置有奶牛能到的个数,个数等于奶牛总数的即合适的牧场。100分代码:#include<bi......
  • a person who had great influence on me
    Sheisofmediumbuildandaboutmyheight.Whenyouseeherstraightblackhairandbigeyes,youwillthinkthatsheisaveryniceandsincereperson.Infact,that'sexactlywhosheis。Sheisintrovertedbutcute.Likefluffythings,likepink,k......