当前位置: 首页 > news >正文

MySQL三大日志详解(binlog、undo log、redo log)

MySQL三大日志详解(binlog、undo log、redo log)

MySQL的日志有很多种类,最终要的有三种,binlog、redo log和undo log日志。他们分别是用来主从复制(备份恢复)、故障恢复和事务回滚的。

binlog

binlog是 Server层 的日志,无论存储引擎层使用了什么存储引擎,都可以使用binlog来记录对数据库的更新操作。事务还未提交的时候,这些更新记录会保存在 binlog cache 中,然后事务提交之后,这个binlog cache就会被 追加写 到binlog文件中去。binlog 主要是用来做 主从复制备份恢复 的。

主从复制

主库在提交了一次更新数据库操作的事务时,就会把这次操作记录在binlog中,然后会有一个 log dump 线程,不断地把binlog的数据发送给从库,从库中会有一个 I/O线程 来接收从主库传来的binlog,将它放在从库的 relay log 中保存,并且还会有一个sql线程来读取这个relay log中最新的日志,然后执行它,以此保证了主库和从库的一致性。

同步复制: 主库在写完一次binlog之后,也就是一次事务提交之后,必须要等待所有从库都复制成功并且响应之后,才向客户端返回这次更新操作的结果。这种性能特别差,基本不考虑使用。

异步复制: 主库执行完提交事务之后就立刻返回客户端响应,不会去等待从库的复制,这种方式有个缺点,就是我们一般会在主库宕机的时候使用一个从库来当主库,所以如果主库提交事务之后,binlog还未同步到从库的过程中间宕机了,那么我们切换的从库来当新的主库就会丢失数据。异步复制是mysql默认情况下的主从复制模型。

半同步复制: 这种模型结合了同步复制和异步复制模型,当主库提交一条事务之后,会等待一个从库的同步完成,而不是等待所有从库的同步完成,就会响应客户端。

undo log

我们都知道一个事务在提交之前,这个事务对数据库所做的一切操作是没有被持久化的,如果事务崩溃,那么这个事务崩溃之前所做的操作都需要被回滚,那么mysql是怎么做回滚操作的呢?就是依靠这个undo log。

当每次执行 增、删、改 操作的时候,mysql都会为对应数据生成一条undo log,也就是这个操作之前的该条数据,如果事务崩溃了需要回滚,就会依靠这个undo log来进行回滚操作。

插入 一条记录的时候,会把这条记录的主键值记下来,回滚的时候删除这个主键值。

删除 一条记录的时候,会把这条记录的内容都记下来,回滚的时候插入会去。

修改 一条记录的时候,会把更新的记录的旧值记录下来,回滚的时候更新回旧值。

一条记录的每一次产生的undo log都会有一个 trx_idroll_pointer 字段,分别用来记录时哪个事务修改的,和这条记录的上一次修改的undo log。由roll_pointer串联起来的一条记录就形成了该条记录的 版本链

可以通过read view+undo log来实现 MVCC。

redo log

buffer pool 增加了读写效率,但是它是基于内存来暂时保存数据的更新的,那么就会有丢失的风险,redo log就是为了防止这里的数据丢失而出现的。

我们知道我们使用了buffer pool增加读写效率之后,对数据的修改就不是直接落盘的了,而是将修改的数据页标记为脏页,然后在特定时机将脏页刷新到磁盘。每次在更新数据的时候,不仅操作缓存页,还会写一条redo log保存在 redo log buffer中来保存这次的更新,redo log buffer会定时保存到磁盘中去,也会在事务提交的时候持久化到磁盘(根据选择刷盘的策略不同)(redo log数据量小,磁盘I/O就快,并且是追加写,也就是 顺序写 ,而如果直接写入数据就是 随机写 ,所以持久化日志可以快速地持久化数据)。undo log在buffer pool中也有一个缓存的,它的刷盘策略和普通的数据页是一样的,也是要依靠redo log来防止数据丢失。注意redo log是 循环写 ,binlog是 追加写

两阶段提交

undo log是依靠redo log来进行持久化保存的,所以它的刷盘成功与否在于redo log是否正常执行了。而redo log和binlog刷盘的时机都有在事务提交的时候刷盘,但是这两个操作是独立的,所以就会有可能出现redo log刷盘成功而binlog失败 或者 binlog成功,redo log刷盘失败的不一致情况。

MySQL为了解决这个两种日志之间的不一致问题,就提出了 两阶段提交 的方法来解决。两阶段提交方法其实是 分布式事务一致性协议 ,它可以保证多个逻辑操作要么全部成功,要么全部失败,不会出现 半成功 的状态。

MySQL在事务提交时,持久化redo log 和 binlog时使用 内部XA事务 ,分两阶段来完成这个事务,这个事务完成之后就代表整体事务的提交成功,redo log和 binlog都持久化完成。内部事务也有内部事务id(XID)。

prepare阶段: 将XID写入redo log,然后redo log事务状态设置为prepare,持久化到磁盘。

commit阶段: 将XID写入到binlog,binlog持久化到磁盘,接着将redo log的prepare状态调整为commit状态,该状态不需要持久化到磁盘,只要binlog 持久化到磁盘,那么redo log无论是哪个状态,都代表它已经被持久化了。

如果在两个阶段之间发生了故障,那么binlog中是没有已持久化了的redo log对应的XID的,那么就会执行回滚,将redo log的prepare状态的数据清除掉。如果binlog中有与redo log中相同的XID,那么无论redo log的状态是prepare还是commit,那么都证明刷盘完成,则提交事务。

所以说,可以说两阶段提交就是固定了两个日志持久化的顺序,然后以binlog写成功为事务提交成功的标识。

http://www.lryc.cn/news/609870.html

相关文章:

  • 赋能未来:数字孪生驱动能源系统智能化升级
  • 【项目实践】在系统接入天气api,根据当前天气提醒,做好plan
  • Linux(centos)安全狗
  • 【芯片设计专用执行单元:PWM如何重塑能源与智能控制】
  • sqli-labs靶场less29~less35
  • 2025.08.04 移除元素
  • 【测试工程思考】测试自动化基础能力建设
  • 使用mybatis生成器生成实体类mapper和查询参数文件,实现简单增删改查。使用log4j输出日志到控制台。使用配置文件注册Bean,配置视图解析器
  • 每天学一个Linux命令(38):vi/vim
  • Excel商业智能分析报表 【销售管理分析仪】
  • 免费MCP: JSON 转 Excel MCP
  • Vim 高效使用指南
  • Flutter 事件总线 Event Bus
  • HarmonyOS 多屏适配最佳实践:基于 ArkUI 的响应式 UI 方案
  • 计算机网络:理解路由的下一跳
  • 第四十六章:AI的“瞬时记忆”与“高效聚焦”:llama.cpp的KV Cache与Attention机制
  • C++ 中 initializer_list 类型推导
  • 2.1 vue组件
  • 【AMD】编译llama.cpp实践版
  • 【异常案例分析】使用空指针调用函数(非虚函数)时,没有崩溃在函数调用处,而是崩在被调用函数内部
  • 关于大数据的基础知识(三)——数据安全与合规
  • C++模板知识点3『std::initializer_list初始化时逗号表达式的执行顺序』
  • 1.kotlin数组、集合常用方法
  • 【iOS】渲染原理离屏渲染
  • 网络安全 | 从 0 到 1 了解 WAF:Web 应用防火墙到底是什么?
  • 国内首个开源SCA社区——OpenSCA开源社区
  • C++临时对象:来源与性能优化之道
  • 前后端流式交互的几种方式
  • Petalinux快捷下载
  • 【笔记】ROS1|2 Turtlebot3汉堡Burger连接和远程控制【旧文转载】