当前位置: 首页 > 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.dtcms.com/a/315249.html

相关文章:

  • C语言的指针
  • 拆解格行随身WiFi技术壁垒:Marvell芯片+智能切网引擎,地铁22Mbps速率如何实现?
  • mysql 数据库系统坏了,物理拷贝出数据怎么读取
  • 深入剖析通用目标跟踪:一项综述
  • 关于如何自定义vscode(wsl连接linux)终端路径文件夹文件名字颜色的步骤:
  • 自学嵌入式 day 42 串口通信
  • 力扣热题100——双指针
  • 应⽤层协议HTTP
  • 个推1.0版本
  • 自动化测试工具Katalon之BDD
  • 鸿蒙开发-端云一体化--云数据库
  • Qt 自动无法加载数据库为空
  • 知识管理中的人工智能:概述、主要功能和管理工具
  • 专访 Giants Protocol 创始人:新加坡主权基金正式押注进军 RWA
  • 深入理解 mmap:原理、用法与实战全解析
  • Linux 进程间通信底层原理(1):匿名与命令管道
  • LLM Prompt与开源模型资源(4)提示词工程进阶指南
  • Node.js高并发接口下的事件循环卡顿问题与异步解耦优化方案
  • 抛出自定义异常
  • 普及冲奖——贪心补题报告
  • MySQL详解
  • Docker 和Docker-compose常用命令
  • STM32标准库的工程创建
  • 推荐广告搜索三种业务的区别
  • 非机动车乱停放识别准确率↑37%:陌讯多特征融合算法实战解析
  • 04-Chapter02-Example01
  • 【cooragent多智能体】各个单智能体的输入与输出(实际案例)
  • Jmeter进阶(笔记)
  • 进程间通信:管道与共享内存
  • 亚马逊广告进阶:如何选择提曝光还是控曝光