你想知道undo log的作用都在这里

2023-11-10

今天我们来介绍下mysql的undo log 日志,带你更加深入理解它的作用。

01.为什么需要 undo log?

考虑一个问题。一个事务在执行过程中,在还没有提交事务之前,如果mysql发生了崩溃,要怎么回滚到事务之前的数据呢?

如果我们每次在事务执行过程中,都记录下回滚时需要的信息到一个日志里,那么在事务执行中途发生了mysql崩溃后,就不用担心无法回滚到事务之前的数据,我们可以通过这个日志回滚到事务之前的数据。再者当用户用一条rollback语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。

实现这一机制就是 undo log(回滚日志),它保证了事务的 ACID 特性中的原子性。

undo log除了可以做回滚操作,还有一个作用就是MVCC,当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。

MVCC实现是通过read view + undo log,undo log 为每条记录保存多份历史数据,形成一个版本链。(read view下次讲MVCC的时候再细说)。

02.Undo log版本链

当一直有事务对该行改动时,就会一直生成undo log,最终将会形成undo log版本链。

在讲版本列之前先讲下行的隐藏列有哪些?

在数据库中的每一行上,除了存放真实的数据以外,还存在着3个隐藏列row_id、trx_id与roll_pointer

row_id(行号

如果当前表有整数类型的主键,则row_id就是主键的值。

如果没有整数类型的主键,则mysql会按照字段顺序选择一个非空的整数类型的唯一索引作为row_id。

如果mysql没有找到,则会自动生成一个自动增长的整数作为row_id。

trx_id(事务号)

当一个事务开始执行前,mysql会为这个事务分配一个全局自增的事务id。之后该事务对当前行进行的增、删、改操作时,都会将自己的事务id记录到trx_id中。

roll_pointer(回滚指针

事务对当前行进行改动时,会将旧数据写入进undo log中,再将新数据写入当前行,且当前行的roll_pointer指向刚才那个undo log,因此可以通过roll_pointer找到该行的前一个版本。

我们使用以下语句创建一个person表

CREATE TABLE `person` (  `id` int(11) NOT NULL,  `name` varchar(255) DEFAULT NULL,  `age` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB

现在开启第1个事务,事务id为1,执行以下插入语句。

INSERT INTO `person`(`id`, `name`, `age`) VALUES (1, '张三', 18);

那么当前行的一个示意图如下:

因为该数据是新插入的,因此它的roll_pointer指向的undo log为空。

接着开启第2个事务,分配到事务id是2,执行以下修改命令。

UPDATE`person` SET `name` = '李四' WHERE `id` = 1

当开启第3个事务,分配到事务id是3,执行以下修改命令。

UPDATE`person` SET `age` = '22' WHERE `id` = 1

每一个事务对该行改动时,都会生成一个undo log,用于保存之前的版本,之后再将新版本的roll_pointer指向刚才生成的undo log。

因此roll_pointer可以将这些不同版本的undo log串联起来,形成undo log版本链

03.undo是逻辑日志还是物理日志?

用户通常对undo有这样的误解,undo用于将数据库物理地恢复到执行语句或事务之前的样子,但实际不是的,undo是逻辑日志因此只是将数据逻辑地恢复到原来的样子。所有修改都被逻辑地取消,但是数据结构和页本身在回滚之后可能大不相同。

比如,一个事务在修改当前一个页中某几条记录,同时还有别的事务在对同一个页中另几条记录进行修改。因此,不能将一个页回滚到事务开始的样子,因为这样会影响其他事务正在进行的工作。

假设用户执行了一个insert 100条记录的事务,这个事务会导致分配一个新的段,即表空间会增大。在用户执行rollback时,会将插入的事务进行回滚,但是表空间的大小并不会因此而收缩。

因此,当事务回滚时,它实际上做的是与先前相反的工作。

比如:

  1. 对于每个insert,InnoDB存储引擎会完成一个delete。

  2. 对于每个delete,InnoDB存储引擎会执行一个insert。

  3. 对于每个update,InnoDB存储引擎会执行一个相反的update,将修改前的行放回去。

04.undolog怎么样存储?

InnoDB存储引擎对undo的管理同样采用段的方式。InnoDB存储引擎有rollback segment,每个回滚段中记录了1024个undo log segment,在每个undo log segment段中进行undo页的申请。

从InnoDB1.2版本开始,可通过参数对rollback segment做进一步的设置。这些参数包括:

  1. innodb_undo_directory 用于设置rollback segment文件所在的路径。

    该参数默认值为“.”,当前InnoDB存储引擎目录,即存于共享表空间中(ibdataX),可以通过此参数设置到其他位置。

  2. innodb_undo_logs 用来设置rollback segment的个数,默认值为128。

  3. innodb_undo_tablespaces 用来设置构成rollback segment文件的数量。

    这样rollback segment可以较为平均地分布在多个文件中。

    设置该参数后,会在路径innodb_undo_directory看到undo为前缀的文件,该文件就代表rollback segment文件。

  4. innodb_undo_log_truncate(5.7新增):默认关闭。如开启,当undo超过innodb_max_undo_log_size时,会被truncate到初始化大小,(前提:1:里面的undo不再被使用;2:至少需要2个undo tablespaces)可以通过设置innodb_purge_rseg_truncate_frequency调整truncate频率。

事务在undo log segement分配页写入undo log的这个过程同样需要写入重做日志。当事务提交时,InnoDB存储引擎会做以下两件事:

  1. 将undo log 放入列表中,以供之后的purge操作

  2. 判断undo log所在的页是否可以重用,若可以分配下个事务使用

事务提交后并不能马上删除undo log以及undo log所在的页。这是因为可能还有其他事务需要通过undo log来得到行记录之前的版本。故事务提交时将undo log放入一个链表中,是否可以删除undo log 以及undo log所在的页由purge线程决定(purge线程下回细说)。

innodb引擎设计中对undo页可以进行重用。当事务提交时,首先将undo log 放入链表中,然后判断undo页的使用空间是否小于3/4,若是则表示该undo页可以被重用,之后新的undo log记录在当前的undo log的后面,由于存放undo log的列表是以记录进行组织的,而undo页可能存放着不同事务的undo log,因此purge操作需要涉及磁盘的离散读取操作,是一个比较缓慢的过程。

05.undolog需不需要持久化?

undo log的产生会伴随着redo log的产生,这是因为undo log也需要持久性的保护。(redo log下回细说)

06.undolog格式

  • insert undo log

  • update undo log

inert undo log是指在insert操作中产生的undo log。因为insert操作的记录,只对事务本身可见,对其他事务不可见,故该undo log可以在事务提交后直接删除。不需要进行purge操作。

update undo log记录的是对delete和update操作产生的undo log。该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undolog链表,等待purge线程进行最后的删除。

总结下undo log 两大作用:

实现事务回滚,保障事务的原子性。事务处理过程中,如果出现了错误或者用户执 行了 rollback 语句,mysql可以利用 undo log 中的历史数据将数据恢复到事务开始之前的状态

实现 MVCC(多版本并发控制)关键因素之一。MVCC 是通过 read view+ undo log 实现的。undo log 为每条记录保存多份历史数据,MySQL 在执行快照读(普通 select 语句)的时候,会根据事务的 read view 里的信息,顺着 undo log 的版本链找到满足其可见性的记录。

END

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

你想知道undo log的作用都在这里 的相关文章

随机推荐

  • 纯css画三角形

    思路 用border实现 lt html lang en gt lt head gt lt meta charset UTF 8 gt lt meta name viewport content width device width ini
  • 数学形态学滤波学习

    一 概述 数学形态学是建立在集合论基础上了一门学科 具体在图像处理领域 它把形态学和数学中的集合论结合起来 描述二值或灰度图像中的形态特征 来达到图形处理的目的 形态学主要是通过结构元素和图像的相互作用对图像进行拓补变换从而获得图像结构信息
  • 常用的概率分布:伯努利分布、二项分布、多项式分布、高斯分布、指数分布、拉普拉斯分布和Dirac-delta分布

    伯努利分布 Bernoulli distribution 伯努利分布 单个二值随机变量的分布 由单个参数 0 1 控制 例 抛硬币 正面朝上的概率 二项式分布 binomial distrubution 二项式分布 在n次试验中事件A恰好发
  • Android AIDL示例-RemoteCallbackList添加移除监听

    前言 AIDL是一个缩写 全称是Android Interface Definition Language 也就是Android接口定义语言 它是用来实现进程间通讯的 本文使用AIDL写一个小demo来实现夸进程间通讯 本文接着这一篇文章写
  • Git管理工具对比(GitBash、EGit、SourceTree)

    Git管理工具对比 GitBash EGit SourceTree GitBash是采用命令行的方式对版本进行管理 功能最为灵活强大 但是由于需要手动输入希望修改的文件名 所以相对繁琐 EGit是Eclipse的Git插件 最为纠结的一个软
  • 小乌龟Tortoisegit官方汉化包 中文语言安装

    进入小乌龟官网的Download界面下拉在Language中选择中文语言包简体 https tortoisegit org download 下载后直接双击 一步到位安装好 不用管安装路径 在桌面右键点击Tortoisegit选择Setti
  • 如何快速建立一个优秀的账号体系

    在2014年下半年开始 只支持第三方账号登陆的应用在提交苹果的appstore审核的时候被拒绝 拒信如下 If we chose to log in with 微信 we were required toinstall 微信 before
  • org.hibernate.UnknownEntityTypeException: Unable to locate persister:

    springboot2 0 当把Application放到其他包里面时 会出现标题的异常 针对此异常的解决办法是 增加jpa的配置类 使其能扫描到所有的bean package com bmSystem common sys config
  • 微信公众平台错误代码40164的解决方案

    获取微信公众号授权失败 请稍后重试 公众平台返回原始数据为 错误代码 40164 错误信息 invalid ip not in whitelist hint 59FKqA0797e514 错误解释 调用接口的IP地址不在白名单中 请在接口I
  • 车道线检测

    3D车道线单目检测方法 ONCE 3DLanes GitHub once 3dlanes once 3dlanes benchmark 斑马线 检测 上海交大 CDNet 基于YOLOv5改进的 人行道 斑马线和汽车过线行为检测 jacke
  • 详解vue中的v-model

    序 v model是v bind和v on input的结合 即监听了表单的input事件 然后修改value属性对应的值 一 vue单文件中使用v model 众所周知 当我们使用v bind绑定prop时 数据流的流向是从model层流
  • Centos7安装Redis并设置开机自启动图文详解

    1 下载redis wget http download redis io releases redis 6 0 0 tar gz 如果提示没有wget使用如下命令 yum y install wget 2 安装 解压 tar zxvf r
  • 【ES】Elasticsearch Java Rest Client (Document APIs)官方文档中文翻译

    这里写目录标题 一 文档APIs 1 单文档 API Index API Get API Get Source API Exists API Delete API Update API Term Vectors API 2 多文档 API
  • Linux本地套接字

    LINUX和UNIX都拥有一个非常实用的工具 UNIX套接字 或称为本地套接字 它可以被用在进程间通讯 IPC 当中 UNIX套接字的运转机制和Internet套接字类似 主要的区别UNIX套接字只能用在一台计算机中 而Internet套接
  • Linux(ubuntu)安装libevent

    步骤如下 第一步下载压缩包文件 libevent 2 1 8 stable tar gz 地址 https github com libevent libevent releases download release 2 1 8 stabl
  • 李沐论文精读系列四:CLIP和改进工作串讲(LSeg、GroupViT、VLiD、 GLIPv1、 GLIPv2、CLIPasso)

    文章目录 一 CLIP 1 1 简介 1 1 1 前言 1 1 2 模型结构 1 1 3 模型效果 1 1 3 1 对自然分布偏移的鲁棒性 1 1 3 2 StyleCLIP 1 1 3 3 CLIPDraw 1 1 3 4 zero sh
  • 互联网拥塞控制终极指南

    本文为媒矿工厂翻译的技术文章 原标题 The Ultimate Guide to Internet Congestion Control 原作者 Michael Schapira 原文链接 https www compiralabs com
  • sqlserver 查看表所占磁盘空间

    方法1 可以通过SP SPACEUSED来查看 sp spaceused 显示行数 保留的磁盘空间以及当前数据库中的表所使用的磁盘空间 或显示由整个数据库保留和使用的磁盘空间 语法 sp spaceused objname objname
  • ubuntu开机出现initramfs解决办法

    今天上班打开ubuntu的虚拟机的时候出现了这个界面 注意倒数第三行 说 dev sda1 需要 fsck 第一步 执行命令 fsck dev sda1 y 第二步 当出现FILE SYSTEM WAS MODIFIED这个的时候 就表示已
  • 你想知道undo log的作用都在这里

    今天我们来介绍下mysql的undo log 日志 带你更加深入理解它的作用 01 为什么需要 undo log 考虑一个问题 一个事务在执行过程中 在还没有提交事务之前 如果mysql发生了崩溃 要怎么回滚到事务之前的数据呢 如果我们每次