了解mysql的undo log

第一次了解mysql的时候,看到了undo log这个名词,却不知道undo log是干什么,为了能够继续看明白一些mysql的资料,不得不先弄明白undo log是什么? undo log的原理是什么?它与数据库的其它特性如何配何。
这篇笔记只从原理上分析,不涉及具体的实现方法。

undo log是什么?

undo log是一种日志,日志中记录对于数据库的反向操作。
如果把数据库的内容当做一种状态机,那么数据的写操作就是修改状态机的命令,而undo 就对应修改状态机的反向命令。
所以理论上每一个对于状态机修改的命令都会产生对应一条相当的undo log,以便事务回滚的时候,能够把状态机修改到事务原来的样子。
假如我们有一个事务:
create table table1(c1 int);
begin transaction;
insert into table1 (100); //数据库执行这一条命令的时候应该产生一条undo日志,能够把这语句对于状态机的修改回复到原来没有修改的状态 , undo 应该是 delete table1 where c1 = 100;
insert into table1(200); // undo 应该是 delete table1 where c1 = 200;
update table1 set c1 = 300 where c1 = 200; // undo: update table1 set c1 = 200 where c1 = 300
rollback;

为什么要有undo log, 或者说undo log解决了什么问题?

其实这个问题问的不好,因为undo是设计出来,没有什么直接的因素说非得有undo log, 自己比较熟习的postgres就没有undo log。下面就与postgres进行比较,来看mysql为什么有undo
mysql与postgres都是基于mvcc的,但是mysql与postgres对于mvcc的实现不太一样。
为什么要有mvcc? 因为mvcc与它的前辈lock based相比,能够实现读写不冲突这一个特性,如果没有mvcc,一个事务读一条数据,另外一个事务写同一条数据,这两个事务是无法并发执行的,后一个事务必须要等前一个事务执行完成之后才能执行,但是有了mvcc,这两个事务就可以并发执行,这及大的提高的数据库的性能,以至于现在主流的数据库都实现了mvcc。
但是各个数据对于mvcc的实现略有不同:
其中mysql的实现就有undo log,而postgres的实现里面没有undo log.但是postgres里面有clog, clog记录了每一事务的状态。
postgres的每一行的所有的版本是存放一起的,它允许保留aborted事务产生的版本, mysql的最新版本保存在表空间,而历史版本则保存在undo log里面。mysql在事务回滚的时候,应该是同步利用undo log把最新版本的恢复成修改之前的状态,同时删除对应事务产生的undo log,而postgres则是通过异步的vaccum,来把aborted事务产生的历史版本给删除。
mvcc里面最重要的一点就是行可见性判断。这里简单的描述一下postgres的行可见性判断与mysql的行可见性判断。

  • mysql与postgres都会为每一个事务赋予一个xid,这个xid在数据库内部是单高递增的,它唯一标识了一个事务,同时它定义了数据库中事务相关事件的先后顺序。(这里的事务相关事件主要指begin transaction)
  • mvcc里面的snapshot读要求每一个事务(或者第一个语句,因为事务隔离级别的不同决定是一个事务一个snapshot还是一个语句一个snapshot)都要有一个snapshot,而mysql与postgres都选择使用当前活动事务的列表来作为snapshot. 每一个事务开始的时候(一个语句开始的时候)获取一下当前整个系统所有已经开始但没有结束的事务的xid.
  • mysql与postgres对于每一行的每一个版本都记录了两个字段x_min, x_max(mysql不知道叫啥,但是意思应该差不多), x_xmin代表创建这一个版本对应事务的xid, x_max表示删除这个版本对应的事务的xid
  • 判断一个版本是否可见,postgres需要以下几个信息:

    • 当前事务的snapshot(活动事务列表)
    • clog,可以根据xid来查询当前事务的状态,事务有三个状态pending, committed, aborted
    • 一个版本上的x_min, x_max
    • 首先,postgres先看一下,x_min对应的xid是否在snapshot中能够找到,如果能够找到,说明对应snapshot开始的时候,创建这个版本的事务还没有结束,直接返回该版本不可见
    • 如果x_min在在snapshot里面找不到,说明在取snapshot的时候,创建这一行的事务已经结束,事务结束分两种状态,aborted, committed
      • 通过查询clog,看x_min对应的事务是不是aborted, 如果是aborted, 说明创建这一行的事务已经回滚, 该行不可见
      • 如果事务是committed: 说明创建该行的动作在snapshot之前已经结束,这个时候还需要分情况:
        • 该行的x_max为空,就行是最新的版本,直接返回该行可见
        • 该行有x_max, 但是x_max对应的事务也在snapshot列表里面,说明取snapshot的时候,删除该行的事务还没有结束,该操作对应snapshot不可见,返回该行可见。
        • 该行有x_max, 同时x_max也不在snapshot列表里面,但是x_max对应的clog为aborted, 说明删除操作对应的事务aborted,返回该行可见
        • 该行有x_max, 同时x_max也不在snapshot列表里面,但是x_max对应的clog为committed, 说明删除该行的操作在snapshot之前已经成功,返回该行不可见。
  • mysql的行可见性应该会简单一点,因为历史版本里面只保存成功提交的版本

    • 行可见性判断的几个参数:对应事务(语句)的snapshot, x_min, x_max
    • x_min存在于snapshot中,该行不可见
    • x_min不存在于snapshot中,没有x_max, 该行可见。(该行是最新版本ujn8)
    • x_min不存在于snapshot中,同时x_max也不存在于snapshot列表中,该行不可见,说明删除操作在snapshot之前已经完成。

什么时候要使用到undo

上面已经提到,undo这个动作发生成rollback一个事务的时候。
同时也发生在数据recovery的时候,因为有些事务正在执行过程中,数据crash了,那么数据库重启做完redo后,要把对应没有提交的事务的动作undo一下。
同时undo log记录历史版本,读历史版本的时候,也要从undo log里面去读。

以上关于mysql的都是自己从互联网上看资料得来的,理解的并不一定正确,后面会根据mysql代码来验证一下。

时间: 2024-10-12 11:53:49

了解mysql的undo log的相关文章

说说MySQL中的Redo log Undo log都在干啥

阅读目录(Content) 1 undo 1.1 undo是啥 1.2 undo参数 1.3 undo空间管理 2 redo 2.1 redo是啥 2.2 redo 参数 2.3 redo 空间管理 3 undo及redo如何记录事务 3.1 Undo + Redo事务的简化过程 3.2  IO影响 3.3 恢复 在数据库系统中,既有存放数据的文件,也有存放日志的文件.日志在内存中也是有缓存Log buffer,也有磁盘文件log file,本文主要描述存放日志的文件. MySQL中的日志文件,

MySQL的日志(二):事务日志(redo log和undo log)

本文目录:1.redo log 1.1 redo log和二进制日志的区别 1.2 redo log的基本概念 1.3 日志块(log block) 1.4 log group和redo log file 1.5 redo log的格式 1.6 日志刷盘的规则 1.7 数据页刷盘的规则及checkpoint 1.8 LSN超详细分析 1.9 InnoDB的恢复行为 1.10 和redo log相关的变量2.undo log 2.1 undo log的基本概念 2.2 undo log的存储方式

mysql中的事务隔离级别及可重复读读提交详细分析(mvcc多版本控制/undo log)

一.事物隔离级别 读未提交(read uncommitted)是指,一个事务还没提交时,它做的变更就能被别的事务看到.通俗理解,别人改数据的事务尚未提交,我在我的事务中也能读到. 读提交(read committed)是指,一个事务提交之后,它做的变更才会被其他事务看到.通俗理解,别人改数据的事务已经提交,我在我的事务中才能读到. 可重复读(repeatable read)是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据 是一致的.当然在可重复读隔离级别下,未提交变更对其他事

【转载】MySQL 日志 undo | redo

本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomicity)  事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作.如果在执行的过程中发生  了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过. - 原理  Undo Log的原理很简单,为了满

【msql】redo and undo log

Innodb Crash Recovery InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性.和大多数关系型数据库一样,InnoDB记录了对数据文件的物理更改,并保证总是日志先行,也就是所谓的WAL,即在持久化数据文件前,保证之前的redo日志已经写到磁盘 Crash Recovery是InnoDB引擎的一个特点,当故障发生,重新启服务后,会自动完成恢复操作,将数据库恢复到之前一个

浅析如何将undo log从tablespace分离

从MySQL5.6.3之后,MySQL支持将undo日志从tablespace(ibdataN)中独立开来放到单独的磁盘上.MySQL官方建议将undo放到ssd上,而把ibdata放在hd.(这里似乎有争论,国内某些大牛建议将顺序读写的log日志放在hdd) 比较重要的一个概念: 虽然undo log被分离出去了,但是其io处理还是在system tablespace内完成,所以定义上来讲还是算tablespace的.文档中原文如下: "Because these files handleI/

MySQL的redo log结构和SQL Server的log结构对比

MySQL的redo log结构和SQL Server的log结构对比 innodb 存储引擎 mysql技术内幕 f 1 f 2 f 3 f 4 f 5 f 6 f 7 f sqlserver http://www.cnblogs.com/CareySon/p/3308926.html 事务对数据库中每次修改都会分解成多个多个原子层级的条目被记录到持久存储中,这些条目就是所谓的日志记录(Log Record),我们可以通过fn_dblog来查看这些条目.如图2所示. 图2.Fn_dblog 每

[转]MySQL日志——Undo | Redo

本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomicity)  事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作.如果在执行的过程中发生  了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过. - 原理  Undo Log的原理很简单,为了满

5分钟了解MySQL5.7的undo log在线收缩新特性

Part1:写在最前 在MysQL5.6版本中,可以把undo log 回滚日志分离到一个单独的表空间里:其缺点是不能回收空间大小,until MysQL5.7,but MariadDB10.1暂不支持. 本文介绍并演示MysQL5.7是如何在线收缩undo log的. undo log日志是保存在共享表空间ibdata1文件中的,随着数据库的运行时间的不断增长,ibdata1文件会越来越大,在以往的MySQL数据库版本中,如果我们想要回收ibdata1文件所占空间,会非常的复杂和困难,必须先将