MySQL中有六种日志文件,
分别是:重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志(errorlog)、慢查询日志(slow query log)、一般查询日志(general log),中继日志(relay log)。
其中重做日志和回滚日志与事务操作息息相关,二进制日志也与事务操作有一定的关系,这三种日志,对理解MySQL中的事务操作有着重要的意义。

undo是将用户上一步做的操作对程序造成的改动恢复到改动之前,而redo操作是指重新实现这种改动。

undo/redo操作的实现方式分为两类:记录数据和记录操作。

记录数据是指将信息编辑窗口打开时,保存原始数据,然后记录用户每次操作后的结果数据,这里的数据是指信息编辑窗口中所有可能发生变动的数据。做undo操作时程序将用户上一步操作前的数据传给信息编辑窗口相应控件。这种做法是以空间来换时间,程序不必考虑用户到底改变了哪些数据,反正每次都是替换的所有可能改变的数据。当每次保存的数据量比较小时,这种做法比较方便快捷,但是如果数据量大,比如包括图形、视频信息等,这种方法就比较耗费内存了。

记录操作是指信息编辑窗口打开后,记录用户每次的操作,包括具体的操作动作以及操作改变的数据,这里的数据是指既能还原操作的数据又能重复操作的数据。做undo操作时程序根据记录的用户操作进行反向处理,对信息编辑窗口进行改动,而做redo操作的时候程序根据记录的用户操作来重复用户的操作。这种做法是以时间换来空间,程序记录的信息变少了,每次只需要记录用户的操作类型以及相关的操作数据(比如用户编辑的哪个控件,编辑前后的控件内容分别是什么),与操作无关的其他数据则不需要记录。这种做法比起记录数据的方式肯定要复杂,但是胜于节俭内存。

Oracle中的redo和undo是关键技术的核心, 诸如实例恢复, 介质恢复, DataGuard, 闪回机制等都是给予redo和undo的, 所以很有必要详细梳理这块的知识, 总结记录.

  1. 数据变化日志

    当我们改变一个数据块时, 都记录了哪些日志, 具体是怎么样的流程呢?

    当在Oracle中改变一条数据时, 不仅仅要在数据文件里(可能在buffer里直接找到)找到并修改数据, 更重要的是需要做完善的日志记录, 具体如下:

    • 创建一个重做改变向量, 描述如何往undo块插入一条undo记录(即undo的redo日志)
    • 创建一个重做改变向量, 描述数据块的变化(即data的redo日志)
    • 合并这两个重做改变向量为一条日志记录, 并写到重做日志缓冲区
    • 向undo块插入undo记录
    • 改变数据块中的数据

    图1: 更新操作经历的事件时序图

  2. Redo

    redo处理方式:

    session -> redo日志 -> 写入redo log buffer -> 写到redo日志文件(循环利用) -> 归档到日志中

    写redo log buffer会成为系统的瓶颈

    session每次数据更改都会插入一条redo记录到buffer中, 一个session可能很短时间内做了很多更改, 同时可能有很多session并发操作, 却只有一个redo log buffer.

    • 老机制, redo allocation latch: 保护redo log buffer, 控制对共享区内存的访问.

      session -> 请求redo allocation latch -> 为写入到buffer的信息预留一些空间

      避免了多个进程同时写入buffer相同部分的风险.

        大并发系统会出现latch竞争, cpu空转
    • 新机制, private redo和IMU(In-Memory undo)

      在session的整个事务期间内, 生成所有改变向量, 写入private redo log buffer(PGA中), 当事务提交时, session会将private redo buffer中的记录copy到公共redo log buffer中.

      一个session在一次事务里只需要获取一次公共的redo allocation latch.


      e.g

      脚步更新表记录, 观察期间latch统计信息.

      • 9i的输出:

        Latch Gets Im_Gets
        redo copy 0 51
        redo allocation 53 0
        Name Value
        redo entries 51
        redo size 12,668
      • 10g的输出:

        Latch Gets Im_Gets
        redo copy 0 1
        redo allocation 5 1
        In memory undo latch 53 1
        Name Value
        redo entries 1
        redo size 12,048

      10g里, redo copy latch只命中了一次; redo allocation latch也get很少; 只生成了一个redo entry;

      测试中发现, 貌似竞争问题转移了?


    • 待跟进:
      • 分析v$latch_children, 搞清楚为什么latch活动的变化不是新的威胁(瓶颈);
      • 分析重做日志, 搞清楚那个大的日志条目(redo entry)都记录了什么;
      • 分析动态性能表(x$kcrfstrand和x$ktifp), 理解各种实例活动信息是如何串联到一起的;
    • redo的2组内存结构:
      • x$kcrfstrand, 私有redo区: 处理"前滚"改变向量(私有redo区里也包含传统的"公共"redo log buffer);
      • x$ktifp, IMU区: 处理undo改变向量;

      IMU区中有N多IMU池, N取决于数据库参数transactions/10, 每个池都有自己的latch.

      x$ktifp中的每条记录(即IMU)在x$kcrfstrand中都有对应的一条private redo记录.

      x$kcrfstrand中的每条private redo记录都由其自身的redo allocation latch保护, 每条"公共"的重做记录都由传统的redo copy latch保护.

    • In-Memory undo latch(IMU latch):

      任何一个改变都会产生一次对IMU latch的访问, 用一个latch(IMU latch)代替两个(redo allocation latch与redo copy latch), 至少latch竞争是减半了.

      IMU latch有许多子latch, 每个子latch负责一个IMU内存区域(池).

    • 新机制的redo allocation latch:

      2种latch:

      • 一类保护私有redo线程(private redo thread)
      • 另一类保护公共redo线程(public redo thread)

      每个线程都有自己的latch

  3. undo
    • 读一致性

      块的ITL entries里必须包含一个指向undo记录的指针(指针是有限的)

    • 回滚

数据库中的undo日志、redo日志的更多相关文章

  1. 理解数据库中的undo日志、redo日志、检查点

    数据库存放数据的文件,本文称其为data file. 数据库的内容在内存里是有缓存的,这里命名为db buffer.某次操作,我们取了数据库某表格中的数据,这个数据会在内存中缓存一些时间.对这个数据的 ...

  2. SQLServer数据库中开启CDC导致事务日志空间被占满的原因

    SQLServer数据库中开启CDC导致事务日志空间被占满的原因 转载  2017-04-01   投稿:mrr    我要评论 这篇文章主要介绍了SQLServer数据库中开启CDC导致事务日志空间 ...

  3. 关于数据库一致改关闭下redo日志文件丢失的处理办法的总结

    数据库一致性关闭下redo日志文件丢失的处理办法(归档和非归档都行) 1. inactive log  在一致性关闭后删除重启时可以在mount下(不丢失数据) alter database clea ...

  4. SQLServer数据库中开启CDC导致“事务日志空间被占满,原因为REPLICATION”的原因分析和解决办法

    本文出处:http://www.cnblogs.com/wy123/p/6646143.html SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为:在执行增删改语句(产 ...

  5. Visio中的Undo和Redo

    1.Visio默认Undo和Redo操作是可用的,Appliacation中的UndoEnabled标志Undo和Redo操作是否可用. m_Visio.Window.Application.Undo ...

  6. MySQL中redo日志

    重做日志用来实现事务的持久性,即ACID中的D,由两部分组成: 一是内存中的重做日志缓冲(redo log buffer)  易丢失 二是重做日志文件(redo log file) 持久的 InnoD ...

  7. Log4Net的应用教程之保存日志到数据库中

    关于Log4Net的应用,网上有很多教程,但大多数都是拷贝复制,有些按照他的代码来,运行起来发现也出不来效果,但是Log4net的作用实在是非常大的,或者这里说的不对,应该说系统的日志功能是很重要的也 ...

  8. 怎样借助log4j把日志写入数据库中

            log4j是一个优秀的开源日志记录项目.我们不仅能够对输出的日志的格式自定义,还能够自定义日志输出的目的地,比方:屏幕.文本文件,数据 库,甚至能通过socket输出.本节使用MySQ ...

  9. Redo日志

    undo日志有一个潜在的问题,即我们在将书屋改变的所有数据写到磁盘前不能提交该事务.有时,如果让数据库修改暂时只存在于主存中,我们可以节省磁盘IO;只要在崩溃发生时有日志可以恢复,这样做就是安全的. ...

随机推荐

  1. 如何为DigitalOcean上的服务器配置SSH密钥

    本指南适用于mac OS和Linux,windows用户请绕道. 通常,当你启动DigitalOcean droplets时,只要过程完成,你会收到一封电子邮件,让你知道droplets的IP地址和密 ...

  2. RzCheckTree基本使用

    procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin //循环读取勾选节点代码及内容 //StateIndex 1 ...

  3. LVS小型系统架构搭建笔记

    搭建环境说明 本次实现用到了6台节点,实现一个小型的Lvs负载调度 节点1客户端配置代表互联网用户 [root@centos7 network-scripts]# vi ifcfg-ens37 TYP ...

  4. golang 与 c语言 之间传递指针的规则提案

    https://go.googlesource.com/proposal/+/master/design/12416-cgo-pointers.md https://github.com/golang ...

  5. Spark SQL读取Oracle的number类型的数据时精度丢失问题

    Spark SQL读取数据Oracle的数据时,发现number类型的字段在读取的时候精度丢失了,使用的spark版本是Spark2.1.0的版本,竟然最后经过排查和网上查资料发现是一个bug.在Sp ...

  6. 50A

    #include <iostream> using namespace std; int main() { int m, n; cin>>m>>n; cout< ...

  7. 一、程序设计与C语言

    @程序:用特殊的编程语言编写的代码,用于表达如何解决问题. @编程语言的作用:编程语言不是用来和计算机交谈的,而是用它来描述要求计算机如何解决问的过程或方法.计算机只能执行(懂得)机器语言. @辗转相 ...

  8. Lua 随机数生成问题

    原文链接:http://blog.csdn.net/zhangxaochen/article/details/8095007 Lua 生成随机数需要用到两个函数: math.randomseed(xx ...

  9. 19-Python3 函数

    def area(width,heigh): return width*heigh def print_wecome(name): print('welcome',name) print('Runoo ...

  10. CentOS6.5安装sqoop2

    1.下载软件:http://archive.cloudera.com/cdh5/cdh/5/ 2.解压:tar -zxvf mysofts/sqoop2-1.99.5-cdh5.6.0.tar.gz ...