数据库中的事务、undo log、redo log、binlog都是干啥的?

news2024/11/16 3:49:44

文章目录

  • 关于事务
    • ACID 特性
    • undo log
    • redo log
    • redo log 的写入过程
    • 事务的执行过程
    • binlog
    • 细节总结
  • 数据迁移
    • 数据备份工具
    • innodb_autoinc_lock_mode

关于事务

事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消。

ACID 特性

事务的 ACID 特性是指:原子性(Atomicity)、一致性 (Consistency)、隔离性(Isolation)、持久性(Durability)。

  • 原子性:事务是一个不可分割的整体,它在执行过程中不能被中断或推迟,它的所有操作都必须一次性执行,要么都成功,要么都失败。
  • 一致性:事务执行的结果必须满足数据约束条件,不会出现矛盾的结果。注意这里的一致性和我们讨论的分布式环境下的一致性语义有所差别,后者强调的是不同数据源之间数据一致。
  • 隔离性:事务在执行的时候可以隔离其他事务的干扰,也就是不同事务之间不会相互影响。
  • 持久性:事务执行的结果必须保证在数据库里永久保存,即使系统出现故障或者数据库被删除,事务的结果也不会丢失。

undo log

undo log 是指回滚日志,它记录着事务执行过程中被修改的数据。当事务回滚的时候,InnoDB 会根据 undo log 里的数据撤销事务的更改,把数据库恢复到原来的状态。

既然 undo log 是用来回滚的,那么不同的语句对应的 undo log 形态会不一样。

  • 对于 INSERT 来说,对应的 undo log 应该是 DELETE。undo log 记录了该行的主键,后续只需要根据 undo log 里面的主键去原本的聚簇索引里面删掉记录,就可以实现回滚效果。
  • 对于 DELETE 来说,对应的 undo log 应该是 INSERT。undo log 记录了该行的主键,因为在事务执行 DELETE 的时候,实际上并没有真的把记录删除,只是把原记录的删除标记位设置成了 true。所以这里 undo log 记录了主键之后,在回滚的时候就可以根据 undo log 找到原本的记录,然后再把删除标记位设置成 false。
  • 对于 UPDATE 来说,对应的 undo log 也应该是 UPDATE。比如说有一个数据的值原本是 3,要把它更新成5。那么对应的 undo log 就是把数据更新回 3。实际情况稍微复杂一些,基本可以分为以下两种情况:
    • 如果没有更新主键,那么 undo log 里面就记录原记录的主键和被修改的列的原值。
    • 如果更新了主键,那么可以看作是删除了原本的行,然后插入了一个新行。因此 undo log 可以看作是一个 DELETE 原数据的 undo log 再加上插入一个新行的 undo log。

因此,可以看出来:索引、数据、版本链和 undo log有着密切的关系,示意图如下:
在这里插入图片描述

redo log

MySQL的 InnoDB 引擎在数据库发生更改的时候,把更改操作记录在 redo log 里,以便在数据库发生崩溃或出现其他问题的时候,能够通过 redo log 来重做。

你可能会觉得奇怪,InnoDB 引擎不是直接修改了数据吗?为什么需要 redo log?

InnoDB 引擎读写数据的时候,并不是直接操作磁盘的,分为两个步骤:先是读写内存里的 buffer pool,后面再把buffer pool里面修改过的数据刷新到磁盘里面。因此,就可能会出现 buffer pool中的数据修改了,然后突然数据库崩溃了,但是此时数据还没来得及刷新到磁盘。

为了解决这个问题,InnoDB 引擎就引入了 redo log。从流程上来看,相当于InnoDB 先把 buffer pool 里面的数据更新了,再写一份 redo log;等到事务结束之后,就把buffer pool的数据刷新到磁盘里面;万一事务提交了,但是 buffer pool 的数据没写回去,就可以用 redo log 来恢复。

那么问题又来了:redo log 不需要写磁盘吗?如果 redo log 也要写磁盘,干嘛不直接修改数据呢?

redo log 是需要写磁盘的,但是 redo log 是 顺序写 的,也就是 WAL(write-ahead-log) 的一种。不管你要修改的数据在哪个位置以及是否连续,redo log 在磁盘上都是紧挨在一起的。示意图如下:
在这里插入图片描述

由于 顺序写的性能比随机写要好很多,这也是中间件设计里常用的技巧——顺序写取代随机写。

redo log 的写入过程

再考虑一个问题:redo log 是直接一步到位写到磁盘的吗?
答案是:并不是。redo log 写入磁盘也需要两步:

  • (1) 先写进 redo log buffer;
  • (2) 后面再刷新到操作系统的 page cache,或者刷新到磁盘。

在这里插入图片描述
InnoDB 引擎本身提供了参数 innodb_flush_log_at_trx_commit 来控制写到磁盘的时机,里面有三个不同的值:

  • 0:每秒刷新到磁盘,是从 redo log buffer 到磁盘。
  • 1:每次提交的时候刷新到磁盘上,也就是最安全的选项,这个是 InnoDB 的 默认值
  • 2:每次提交的时候刷新到 page cache 里,依赖于操作系统后续刷新到磁盘。

所以,除非把 innodb_flush_log_at_trx_commit 设置成 1,否则其他两个都有丢失的风险。

  • 0:数据提交之后,InnoDB 还没把 redo log buffer 中的数据刷新到磁盘,就宕机了。
  • 2:数据提交之后,InnoDB 把 redo log 刷新到了 page cache 里面,紧接着宕机了。

在这两个场景下, 看上去事务是提交成功了,但是数据库实际上丢失了这个事务。但是并不是说 InnoDB 引擎会严格遵循参数说明的那样来刷新磁盘,还有两种例外情况:

  1. 如果 redo log buffer 快要满了,也会触发把redo log刷新到磁盘里这个动作。一般来说,默认放一半了就会刷新。
  2. 如果某个事务提交的时候触发了刷新到磁盘的动作,那么当下所有事务的 redo log 也会一并刷新。毕竟大家的 redo log 都是放在 redo log buffer里,有人需要刷新了,就顺手一起刷新了。(类似于你去买咖啡,顺手帮你同事也带一杯。)

以上就是 undo log 和 redo log 的用法和机制,那么,InnoDB 是如何通过这样的机制来实现事务的?

事务的执行过程

为了更加便于理解,这里我用一个 UPDATE 语句执行的例子来向你介绍MySQL中 InnoDB 引擎的事务执行过程。假如说原本 a = 3,现在要执行 UPDATE table_name SET a = 5 WHERE id = 1,这个事务的执行过程大致可以分为下面的步骤:

  1. 事务开始,在执行 UPDATE 语句之前会先查找到目标行,加上锁,然后写入到 buffer pool 里面。
    在这里插入图片描述

  2. 写入 undo log。
    在这里插入图片描述

  3. 更新buffer pool:InnoDB 引擎在内存中更新数据值,实际上就是把 buffer pool 的值更新为目标值 5。
    在这里插入图片描述

  4. 写入 redo log。
    在这里插入图片描述

  5. 提交事务,根据 innodb_flush_log_at_trx_commit 的参数设置,决定是否刷新 redo log。如果是,则此时a=5,否则此时a=3。
    在这里插入图片描述

  6. 刷新 buffer pool 到磁盘:此时 a=5。
    在这里插入图片描述

上面是正常情况下的流程,还有一些特殊情况:

  • 如果在 redo log 已经刷新到磁盘,然后数据库宕机了,buffer pool 丢失了修改,那么在 MySQL 重启之后就会回放这个 redo log,从而纠正数据库里的数据。
  • 如果都没有提交,中途回滚,就可以利用 undo log 去修复 buffer pool 和磁盘上的数据。因为有时候 buffer pool 的脏页会在事务提交前刷新磁盘,所以 undo log 也可以用来修复磁盘数据。

实际上,事务执行过程有很多细节,也要比这里描述得复杂很多。这里描述的也只是一个便于理解的简化版的流程。

binlog

binlog 和 redo log、undo log 看起来有点像,但实际上它们之间的差异确很大。binlog 是用于存储 MySQL 中二进制日志(Binary Log)的操作日志文件,它是 MySQL Server 级别的日志,也就是说所有引擎都有。 它记录了MySQL 中数据库的增删改操作,因此 binlog 主要有两个用途:一是在数据库出现故障时恢复数据;二是用于主从同步。

在事务执行过程中,写入 binlog 的时机 和 redo log 的提交过程结合在一起,被称为「MySQL的两阶段提交」。

  • 第一阶段:redo log Prepare(准备),然后写入 binlog;
  • 第二阶段:redo log Commit(提交)。

如果 redo log Prepare 执行完毕了,并且 binlog 已经写入成功了,如果此时 redo log 提交失败,MySQL 也会认为事务已经提交了。如果 binlog 写入失败,那么 MySQL 就认为提交失败了。所以,这里的关键信息在于看 binlog 是否写入成功

由于 binlog 本身有一些完整性校验的规则,所以在 MySQL 看来,binlog 要么写入成功,要么写入失败,不存在中间状态。

binlog 也有刷新磁盘的时机设定,可以通过 sync_binlog 参数值来控制:

  • 0:默认值,由操作系统决定,写入 page cache 就认为成功了。这个时候数据库的性能最好。
  • N:每 N 次提交就刷新到磁盘,N 越小性能越差。如果 N = 1,那么就是每次事务提交都把 binlog 刷新到磁盘。

细节总结

由于事务的机制比较复杂,涉及 redo log 和 undo log 的各种配合,所以需要考虑到事务执行过程的各种异常情况。当中途某个操作执行成功了,万一数据库宕机,数据库恢复过来之后会怎么处理这个事务。可以简单总结如下:

  • 在 redo log 刷新到磁盘之前,都是回滚。
  • 如果 redo log 刷新到了磁盘,那么就是重放 redo log。
  • 如果 binlog 都已经提交成功了,那么就重放,否则就是回滚。
  • 如果回滚,用 undo log 来恢复数据。
  • 如果没有 undo log 就没有后悔药,没有办法回滚。
  • 如果没有 redo log,写到 buffer pool后,如果宕机了就会丢失数据。
  • 为什么非得引入 redo log,是否可以直接修改数据?—— 直接修改数据就是随机写,性能很差。
  • 如果是要求数据不丢失、一致性要求高的业务,可以考虑调整 sync_binlog 的值为 1。但是代价就是数据库的性能比较差,因为每次提交都需要刷新 binlog 到磁盘上。当然这时候 innodb_flush_log_at_trx_commit 也要使用默认值 1。
  • 如果是对性能要求很高,但是可以容忍一部分数据丢失的业务,可以尝试将 innodb_flush_log_at_trx_commit 设置为 2,让操作系统来决定什么时候刷新 redo log。同时还可以把 sync_binlog 的值调整为 100,进一步提高数据库的性能。

更多参考:《深入理解MySQL中的事务和锁》

数据迁移

如果公司有一个历史悠久的核心系统,可能已经无法维护了,但不管是重构还是重新写一个类似的系统,已有的数据都是不能丢的。这个时候就需要重新设计表结构,并且完成数据迁移。或者,针对原有业务中的单库单表拆分多库多表,也需要设计一个合理的数据迁移方案,把数据从单库迁移到分库分表上。

因此,一个高效、稳定的数据迁移方案是很重要的。

一般情况下,数据迁移的基本步骤大概类似下面这些:

  1. 创建目标数据表(新表)。
  2. 用旧数据表的数据初始化新表。
  3. 执行一次校验,并且修复数据,此时用旧表数据修复目标表数据。
  4. 业务代码开启双写,先写旧表,再写新表,数据以旧表为准。读取旧表。
  5. 开启增量校验和数据修复,保持一段时间。
  6. 切换双写顺序,此时读新表,并且修改业务逻辑为:先写新表,再写旧表,数据以新表为准。
  7. 继续保持增量校验和数据修复。
  8. 切换业务逻辑为新表单写,读写都只操作新表。
  9. 根据自己业务需要考虑旧表是否继续保留,或者删除旧表。

上面提到的「初始化新表」,常规操作思路就是使用旧表的历史备份或者导出旧表的数据,比如使用 mysqldump 可以导出旧表的数据字段结构和数据值。

mysqldump 是一个开源的逻辑备份工具,优点是使用简单,能够直接导出整个数据库。缺点则是导出和导入的速度都比较慢,尤其是在数据量非常大的情况下。针对 mysqldump 可以做一些优化来提高导出和导入的性能,比如:

  • 开启 extended-insert 选项,将多行合并为一个 INSERT 语句。
  • 关闭唯一性检查和外键检查,源表已经保证了这两项,所以目标表并不需要检查。
  • 关闭 binlog,毕竟导入数据用不着 binlog。
  • 调整 redo log 的刷盘时机,把 innodb_flush_log_at_trx_commit 设置为 0。

数据备份工具

MySQL中 常用的两款数据备份工具:mysqldump 和 XtraBackup。

  • mysqldump:用于备份和恢复 MySQL 数据库的命令行工具,它允许用户导出 MySQL 数据库的结构、数据以及表之间的关系,以便在数据库发生问题时进行恢复。它是一个逻辑备份工具,导出的内容是一条一条的 SQL语句。
  • XtraBackup:使用 InnoDB 存储引擎的数据备份技术,支持增量备份和恢复,并且支持多主机备份和恢复。它是一个物理备份工具,相当于直接复制 InnoDB 的底层存储文件。
    在这里插入图片描述

innodb_autoinc_lock_mode

在数据迁移的时候需要考虑如何处理主键问题,innodb_autoinc_lock_mode 参数的值会影响主键的生成策略。

innodb_autoinc_lock_mode 是 InnoDB 引擎里面控制自增主键生成策略的参数,它有三个取值。

  • 0:使用表自增锁,但是锁在 INSERT 语句结束之后就释放了。
  • 1:使用表自增锁,如果是普通的 INSERT INTO VALUE 或者 INSERT INTO VALUES 语句申请了主键就释放锁,而不是整个 INSERT 语句执行完毕才释放。如果是 INSERT SELECT 等语句,因为无法确定究竟要插入多少行,所以都是整个 INSERT 语句执行完毕才释放。在执行 INSERT INTO VALUES 的时候,不管插入多少行,都只申请一次主键,一次申请够,这些主键 必然是连续的。所以你可以从返回的最后一个 ID 推测出全部 ID。
  • 2:使用表自增锁,所有的语句都是申请了主键就立刻释放。

在处理批量插入的时候要注意,如果批量插入用的是 INSERT INTO table_name VALUES (xxx),(xxx),(xxx) 语法,那么生成的主键是连续的,可以从返回的最后一个主键推测出前面其他行的主键。即便此时的 innodb_autoinc_lock_mode 取值是 2 也能保证这一点。但是如果用的是多个 INSERT INTO VALUE 语句,或者 INSERT SELECT 语句,那么这些语句生成的主键就有可能不连续。在双写之前,就要先改造这一类的业务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1860979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于PHP+MySQL组合开发的在线客服小程序源码系统 带完整的安装代码包以及搭建教程

系统概述 源码系统是专门为满足企业在线客服需求而设计的,它集成了多种功能,能够帮助企业实现与用户的实时沟通、问题解答、信息反馈等。通过该系统,企业可以更好地了解用户需求,提升用户体验,增强用户对企业的信任感…

Clark 克拉克变换与克拉克逆变换

一、无刷电机控制原理 如上图所示,通过多个mos管的捷联去控制电机运动,即在电机的ABC三相中都会形成相应的电流变化,每相相差120。 二、Clark变换 但如果通过上面这种改变电流波形的方式去控制电机会变得非常复杂,则Clark变换是…

牛了,LSTM+Transformer王炸结合创新,荣登Nature,精度高达95.65%

【LSTM结合Transformer】的研究方向探索了如何利用Transformer模型处理序列数据的能力以及LSTM在捕捉时间序列依赖性方面的优势。这一方向的意义在于通过融合两种模型的特点,提高了对复杂时空数据的预测准确性,尤其是在智能电网攻击检测、多变量时间序列…

2024三掌柜赠书活动第二十五期:Rust 游戏开发实战

目录 目录 前言 Rust语言概念 关于《Rust 游戏开发实战》 Rust系统编程的核心点 Rust开发的关键技术和工具 内容简介 作者简介 书中前言/序言 内容介绍 《Rust 游戏开发实战》全书速览 图书目录 结束语 前言 技术圈最近的编程语言新秀当属Rust莫属,Rus…

如何与ISSI建立EDI连接?

ISSI是一家总部位于美国的半导体公司,主要设计和销售高性能集成电路 (IC),其产品包括DRAM、SRAM、闪存和模拟电路,广泛应用于汽车、通信、工业和医疗等领域。 和其他半导体行业的企业一样,ISSI通过EDI与其全球合作伙伴传输业务单据…

经典神经网络(12)Transformer代码详解及其在Multi30k数据集上的训练

经典神经网络(12)Transformer代码详解及其在Multi30k数据集上的训练 论文链接:https://arxiv.org/pdf/1706.03762v2 原理可以参考:Self-Attention和Transformer 网络架构图如下: 1 Transformer编码器模块 1.1 Embedding位置编码 在实际…

游戏AI的创造思路-技术基础-机器学习(1)

大坑从此开始~~~~ 目录 1. 定义 2.发展历程和典型事件 2.1. 发展历程 2.2. 典型事件 3. 学习类型 3.1. 监督学习 3.2. 无监督学习 3.3. 半监督学习 3.3.1.定义与基本思想 3.3.2. 发展历程与应用场景 3.3.3. 核心算法与优势 3.3.4. 实际应用案例 3.4. 游戏AI的半监…

高校新生如何选择最优手机流量卡?

一年一度的高考已经结束了,愿广大学子金榜题名,家长们都给孩子准备好了手机,那么手机流量卡应该如何选择呢? 高校新生在选择手机流量卡时,需要综合考量流量套餐、费用、网络覆盖、售后服务等多方面因素,以下…

在Visual Studio Code中使用Phi-3模型

更多数字生产力内容,欢迎关注我的公众号“ONE生产力”。 先前的文章中,我们已经介绍使用LM Studio在本地环境中运行Phi-3。LM Studio是一款革命性的桌面应用程序,它允许用户在自己的计算机上本地运行、管理和部署大型语言模型,但有…

新书速览|Linux C与C++一线开发实践

《Linux C与C一线开发实践》 本书内容 Linux C/C编程在Linux应用程序开发中占有重要的地位,掌握这项技术将在就业竞争中立于不败之地。《Linux C与C一线开发实践》内容针对初中级读者,贴近软件公司一线开发实践。全书厚达620多页,知识点丰富…

Go语言JSON-RPC 实战: `net/rpc/jsonrpc` 包的高效使用指南

Go语言JSON-RPC 实战: net/rpc/jsonrpc 包的高效使用指南 简介jsonrpc 包的基础客户端(Client)创建客户端调用方法 服务器(Server)配置服务器数据类型和错误处理 搭建基础的 JSON-RPC 服务服务端的实现客户端的实现 进…

不懂电路搭建可以学嵌入式编程开发吗?

当然可以学嵌入式编程开发!虽然电路搭建是嵌入式开发中的一部分,但即使你对电路搭建不太了解,也可以从嵌入式编程开发入手。刚好我有一些资料,是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0…

什么是绩效评价?绩效考核的五个标准包括哪些?

什么是绩效评价?绩效评价是指运用一定的评价方法、量化指标及评价标准,对中央部门为实现其职能所确定的绩效目标的实现程度,及为实现这一目标所安排预算的执行结果所进行的综合性评价。   绩效考核的五个标准有: 1、考核标准设置…

解决vscode运行js时突然报错

1. 问题背景 创建JavaScript文件运行,弹出错误:Can’t find Node.js binary “node”: path does not exist. Make sure Node.js is installed and in your PATH, or set the “runtimeExecutable” in your launch.json 这是由于没有配置好setting.js…

cnpm run dev 报错 Error: Cannot find module ‘fs/promises’

主要原因是babel版本冲突 卸载以下依赖可以解决问题: 之后重新安装babel-loader依赖 可能会报以下错误: 接着安装babel-core依赖 项目顺利启动

python turtle 004Hello Kity

代码:pythonturtle004HelloKity资源-CSDN文库 # 作者V w1933423 import math import turtle as t# 设置画笔速度 t.speed(0)# 定义函数画弧 def myarc(t1, r, angle):arc_length 2 * math.pi * r * angle / 360 # 弧长n int(arc_length / 3) 1 # 分割段数step…

电脑启动不了怎么办?教你3招轻松解决!

在使用电脑的过程中,有时我们会遇到一些棘手的问题,其中最常见的就是电脑无法正常启动。这可能是由于硬件故障、软件冲突、系统崩溃等多种原因造成的。本文将详细介绍三种解决电脑启动不了的方法,帮助大家快速恢复电脑的正常使用。 方法1&…

MySQL连接

MySQL工具包 MySQL实现简单链接 一 引入工具包 JBDCUtils,无需更改,直接使用即可。 import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties;public class JDBCUtil {private static String URL;p…

手机远程控制另一台手机的全新使用教程(安卓版)

看完这篇文章,你可以了解到安卓手机如何远程控制安卓手机,以及苹果手机如何远程控制安卓手机。 如果想要用安卓手机远程管控苹果手机,或者苹果手机远程管控另一台苹果手机,请点击查看视频《手机远程管控另一台手机的全新使用教程…

利用百数应用优化制造细节,提升生产效率的技术实践

制造管理是确保企业高效、高质生产的核心环节,对于提高企业的运营效率、质量控制、成本控制、交货期保障、资源优化、创新能力以及风险管理等方面都具有重要意义,它能帮助企业在激烈的市场竞争中保持领先地位,同时实现资源的有效利用和风险的…