MySQL InnoDB存储引擎undo redo解析

本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游

00 – Undo Log

Undo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中。还用Undo Log来实现多版本号并发控制(简称:MVCC)。

- 事务的原子性(Atomicity)

事务中的所有操作,要么所有完毕,要么不做不论什么操作。不能仅仅做部分操作。

假设在运行的过程中发生

了错误,要回滚(Rollback)到事务開始前的状态,就像这个事务从来没有运行过。

- 原理

Undo Log的原理非常easy。为了满足事务的原子性,在操作不论什么数据之前,首先将数据备份到一个地方

(这个存储数据备份的地方称为Undo Log)。然后进行数据的改动。

假设出现了错误或者用户运行了

ROLLBACK语句,系统能够利用Undo Log中的备份将数据恢复到事务開始之前的状态。

除了能够保证事务的原子性,Undo Log也能够用来辅助完毕事务的持久化。

- 事务的持久性(Durability)

事务一旦完毕,该事务对数据库所做的全部改动都会持久的保存到数据库中。为了保证持久性,数据库

系统会将改动后的数据全然的记录到持久的存储上。

- 用Undo Log实现原子性和持久化的事务的简化过程

如果有A、B两个数据。值分别为1,2。

A.事务開始.

B.记录A=1到undo log.

C.改动A=3.

D.记录B=2到undo log.

E.改动B=4.

F.将undo log写到磁盘。

G.将数据写到磁盘。

H.事务提交

这里有一个隐含的前提条件:‘数据都是先读到内存中。然后改动内存中的数据。最后将数据写回磁盘’。

之所以能同一时候保证原子性和持久化,是由于下面特点:

A. 更新数据前记录Undo log。

B. 为了保证持久性,必须将数据在事务提交前写到磁盘。仅仅要事务成功提交,数据必定已经持久化。

C. Undo log必须先于数据持久化到磁盘。假设在G,H之间系统崩溃,undo log是完整的,

能够用来回滚事务。

D. 假设在A-F之间系统崩溃,由于数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务開始前的状态。

缺陷:每一个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO。因此性能非常低。

假设可以将数据缓存一段时间。就能降低IO提高性能。可是这样就会丧失事务的持久性。

因此引入了另外一

种机制来实现持久化。即Redo Log.

01 – Redo Log

- 原理

和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,仅仅要将Redo Log持久化就可以。

不须要将数据持久化。当系统崩溃时。尽管数据没有持久化。可是Redo Log已经持久化。系统能够依据

Redo Log的内容,将全部数据恢复到最新的状态。

- Undo + Redo事务的简化过程

如果有A、B两个数据,值分别为1,2.

A.事务開始.

B.记录A=1到undo log.

C.改动A=3.

D.记录A=3到redo log.

E.记录B=2到undo log.

F.改动B=4.

G.记录B=4到redo log.

H.将redo log写入磁盘。

I.事务提交

- Undo + Redo事务的特点

A. 为了保证持久性。必须在事务提交前将Redo Log持久化。

B. 数据不须要在事务提交前写入磁盘。而是缓存在内存中。

C. Redo Log 保证事务的持久性。

D. Undo Log 保证事务的原子性。

E. 有一个隐含的特点。数据必需要晚于redo log写入持久存储。

- IO性能

Undo + Redo的设计主要考虑的是提升IO性能。虽说通过缓存数据。降低了写数据的IO.

可是却引入了新的IO,即写Redo Log的IO。假设Redo Log的IO性能不好,就不能起到提高性能的目的。

为了保证Redo Log可以有比較好的IO性能,InnoDB 的 Redo Log的设计有下面几个特点:

A. 尽量保持Redo Log存储在一段连续的空间上。因此在系统第一次启动时就会将日志文件的空间全然分配。

以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。

B. 批量写入日志。日志并非直接写入文件。而是先写入redo log buffer.当须要将日志刷新到磁盘时

(如事务提交),将很多日志一起写入磁盘.

C. 并发的事务共享Redo Log的存储空间,它们的Redo Log按语句的运行顺序,依次交替的记录在一起,

以降低日志占用的空间。比如,Redo Log中的记录内容可能是这种:

记录1: <trx1, insert …>

记录2: <trx2, update …>

记录3: <trx1, delete …>

记录4: <trx3, update …>

记录5: <trx2, insert …>

D. 由于C的原因,当一个事务将Redo Log写入磁盘时。也会将其它未提交的事务的日志写入磁盘。

E. Redo Log上仅仅进行顺序追加的操作,当一个事务须要回滚时,它的Redo Log记录也不会从

Redo Log中删除掉。

02 – 恢复(Recovery)

- 恢复策略

前面说到未提交的事务和回滚了的事务也会记录Redo Log,因此在进行恢复时,这些事务要进行特殊的

的处理.有2中不同的恢复策略:

A. 进行恢复时,仅仅重做已经提交了的事务。

B. 进行恢复时。重做全部事务包含未提交的事务和回滚了的事务。然后通过Undo Log回滚那些

未提交的事务。

- InnoDB存储引擎的恢复机制

MySQL数据库InnoDB存储引擎使用了B策略, InnoDB存储引擎中的恢复机制有几个特点:

A. 在重做Redo Log时,并不关心事务性。 恢复时,没有BEGIN。也没有COMMIT,ROLLBACK的行为。

也不关心每一个日志是哪个事务的。虽然事务ID等事务相关的内容会记入Redo Log。这些内容仅仅是被当作

要操作的数据的一部分。

B. 使用B策略就必需要将Undo Log持久化,并且必需要在写Redo Log之前将相应的Undo Log写入磁盘。

Undo和Redo Log的这样的关联,使得持久化变得复杂起来。为了减少复杂度,InnoDB将Undo Log看作

数据,因此记录Undo Log的操作也会记录到redo log中。

这样undo log就能够象数据一样缓存起来,

而不用在redo log之前写入磁盘了。

包括Undo Log操作的Redo Log。看起来是这种:

记录1: <trx1, Undo log insert <undo_insert …>>

记录2: <trx1, insert …>

记录3: <trx2, Undo log insert <undo_update …>>

记录4: <trx2, update …>

记录5: <trx3, Undo log insert <undo_delete …>>

记录6: <trx3, delete …>

C. 到这里,另一个问题没有弄清楚。

既然Redo没有事务性。那岂不是会又一次运行被回滚了的事务?

确实是这样。

同一时候Innodb也会将事务回滚时的操作也记录到redo log中。回滚操作本质上也是

对数据进行改动。因此回滚时对数据的操作也会记录到Redo Log中。

一个回滚了的事务的Redo Log,看起来是这种:

记录1: <trx1, Undo log insert <undo_insert …>>

记录2: <trx1, insert A…>

记录3: <trx1, Undo log insert <undo_update …>>

记录4: <trx1, update B…>

记录5: <trx1, Undo log insert <undo_delete …>>

记录6: <trx1, delete C…>

记录7: <trx1, insert C>

记录8: <trx1, update B to old value>

记录9: <trx1, delete A>

一个被回滚了的事务在恢复时的操作就是先redo再undo,因此不会破坏数据的一致性.

- InnoDB存储引擎中相关的函数

Redo: recv_recovery_from_checkpoint_start()

Undo: recv_recovery_rollback_active()

Undo Log的Redo Log: trx_undof_page_add_undo_rec_log()

时间: 2024-08-27 23:27:44

MySQL InnoDB存储引擎undo redo解析的相关文章

mysql innodb存储引擎的聚集索引

InnoDB聚集索引 MySQL有没有支持聚集索引,取决于采用哪种存储引擎. MySQL InnoDB一定会建立聚集索引,所谓聚集,指实际数据行和相关的键值保存在一块,这也决定了一个表只能有一个聚集索引,即MySQL不会一次把数据行保存在二个地方.InnoDB通常根据主键值(primary key)进行聚集,但是当一个表没有PK怎么办?InnoDB选取聚集索引参照列的顺序是: 1.如果声明了主键(primary key),则这个列会被做为聚集索引2.如果没有声明主键,则会用一个唯一且不为空的索引

MySQL InnoDB存储引擎

MySQL对应InnoDB版本 MySQL 5.1>InnoDB 1.0.X MySQL 5.5>InnoDB 1.1.X MySQL 5.6>InnoDB 1.2.X 后台线程 1.Master Thread 负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性:包括刷新脏页.合并插入缓冲.undo页的回收. 2.IO Thread innodb存储引擎中大量使用了AIO(Async IO)来处理写IO请求来提高数据库的并发性能,共有四类IO线程,分别是:insert buffer t

MySQL InnoDB 存储引擎探秘

在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用,主要特点有:支持事务.行锁设计支持高并发.外键支持.自动崩溃恢复.聚簇索引的方式组织表结构等. 体系架构 InnoDB存储引擎是由内存池.后台线程.磁盘存储三大部分组成. 线程 InnoDB 使用的是多线程模型, 其后台有多个不同的线程负责处理不同的任务 Master Thread Master T

MySQL InnoDB 存储引擎原理浅析

注:本文主要基于MySQL 5.6以后版本编写,多数知识来着书籍<MySQL技术内幕++InnoDB存储引擎>,本文章仅记录个人认为比较重要的部分,有兴趣的可以花点时间读原书. 一.MySQL体系结构 主要包含以下几部分: 1.管理服务于工具组件. 2.连接池与鉴权. 3.SQL接口. 4.查询分析器. 5.优化器组件. 6.缓存与缓冲区. 7.各式的插件式存储引擎. 8.物理文件. 其中存储引擎是基于表,而非数据库. 二.InnoDB体系结构 InnoDB引擎包含几个重要部分: 1.后台进程

MySQL Innodb 存储引擎学习篇

master thread的县城优先级别最高.其内部由几个循环(loop)组成:主循环(loop).后台循环(background loop).刷新循环(flush loop).暂停循环(suspend loop).master thread 会根据数-据库运行的状态在loop,background loop.flush loop 和suspend loop 中进行切换.                每秒一次的操作:        1.日志缓冲刷新到磁盘,即使这个事务还没有提交(总是).   

MySQL InnoDB存储引擎之表(一)

主要介绍InnoDB存储引擎表的逻辑存储以及实现.重点介绍数据在表中是如何组织和存放的. 1.索引组织表(index organized table) 在InnoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表叫索引组织表.在InnoDB存在引擎表中,每张表都有个主键(Primary key),如果在创建表时没有显示定义主键,则会按照如下方式选择或者创建主键:a.判定是否有非空的唯一索引(unique not null),如果有则该列即为主键.若果有多个,则选择建表是第一个定义的非

MySQL InnoDB存储引擎之锁

概念: 锁是用来管理对共享文件的并发访问.innodb会在行级别上对数据库上锁.不过innodb存储引擎会在数据库内部其他多个地方使用锁,从而允许对不同资源提供并发访问.例如操作缓冲池中的LRU列表,删除,添加,移动LRU列表中的元素,为了保证一致性,必须有锁的介入.MyISAM引擎是表锁,而InnoDB提供一致性的非锁定读.行级锁,且行级锁没有相关额外的开销. 锁 table-level locking(表级锁) 整个表被客户锁定.根据锁定的类型,其他客户不能向表中插入记录,甚至从中读数据也受

mysql innodb存储引擎介绍

innodb存储引擎1.存储:数据目录.可以通过配置修改 存储文件:frm,ibd结尾的文件.frm存储表结构,ibd存储索引和数据 存储日志:ib_logfilen文件 2.innodb存储引擎开启或关闭: 关闭innodb_fast_shutdown= 0 完成所有的full purge和merge insert buffer操作(如:做InnoDB plugin升级时) 1 默认,不需要完成上述操作,但会刷新缓冲池中的脏页 2 不完成上述两个操作,而是将日志写入日志文件,下次启动时,会执行

MySQL InnoDB存储引擎排它锁和共享锁的研究

1,共享锁实验 session1 在session1建表lisa并插入数据 mysql> create table lisa(name char(10),age int(5)); mysql> insert into lisa values('lisa','26'); 加给age=26这一行加共享锁 mysql> set autocommit=0; mysql> select * from lisa where age=26 lock in share mode; mysql>