Oracle 数据库恢复操作最关键的依据就是 redo log,它记录了对数据库所有的更改操作。在研究如何提取 redolog 中 DML 操作的过程可谓一波三折,因为介绍 redolog 结构细节的资料实在太少了,不过好在最后大致理清了它的结构,并开发了一个基于日志的同步软件。

本系列文章就记录下研究过程中遇到的问题和使用的分析命令、工具。

1. 什么是 Redo Log

Redo Log 就是一组文件,它们记录了对数据库的所有操作,主要包括:

  • 所有 DML 操作,INSERT\UPDATE\DELETE\SELECT FOR UPDATE
  • 所有 DDL 操作,CREATE TABLE\ALTER TABLE
  • 所有因 Recursive SQL 引起的变化,比如执行 DDL 语句时,Oracle 会隐式的执行其他 SQL 修改数据字典

在数据库事务 COMMIT 之前,Oracle 既会把变化信息写入 Rodo Log 文件,也会把原始数据-即 UNDO Segments 写入。因此,Redo Log 不仅用于恢复数据,还能保护数据回滚。

2. Oracle 如何写入 Redo Log

Oracle 数据库每个实例都有一个 redo thread 负责日志的写入,称为 LGWR,LoG WRiter 的简写。Redo Log 文件至少有两个,LGWR 采用循环覆盖的方式写入:当一个文件写满后,开始写入下一个,当最后一个文件写满后,返回第一个开始写入,如此循环。

这样写入会导致数据丢失吗?默认情况下

数据库日志有两种模式:归档非归档,非归档模式就会有覆盖写入的问题。在归档模式下,当一组 ReodLog 文件写满,发生切换时,Oracle 会保证归档完成前此组文件不被覆盖。

可以使用以下命令手动触发日志切换:

SQL> alter system switch logfile

3. Redo Log 基本结构

Redo Log 是由一系列的 redo record 组成,每个 redo record 又是由一组 change vector 组成,每个 change vector 都记录了对单个数据块的更改操作。

Redo Log 文件在存储结构上,是按存储的,默认情况下块大小是磁盘扇区的大小,通常是 512 字节,它的格式取决于操作系统和数据库版本,这里的分析都是在 Windows Server 2008 R2Oracle 11g 的基础上进行的。

Redo Log 是按顺序写入的,基本格式如下:

前两个块记录的是元信息,分别是:

  • 第1个块记录文件本身的信息,比如文件类型,块大小和块数,这部分称为 File Header - 文件头
  • 第2个块记录数据库实例相关信息,比如数据库SID,数据库版本,这部分称为 Redo Log Header - 重做日志头

结合日志写入方式,从整体上看,读取这一组 Redo Log 文件,在内存中可以把它们看成按块为存储单元的环形缓冲区来处理,解析的过程就是读取一个个 Record

3.1 Redo Record

一个 Redo Record 可能占用一个 block,也可能占用多个 block,也可能只占用 block 的一部分,这取决于它的长度,长度字段就存储在 Record Header 头部,结构如下:

值得注意的是,Record 的长度是动态的,计算方法以及二进制文件字节分析后续文章会详细介绍,这里简单看下使用 system dump 命令导出的头信息:

REDO RECORD - Thread:1 RBA: 0x000009.0000029e.0010 LEN: 0x02ac VLD: 0x0d
SCN: 0x0000.0010c5e6 SUBSCN: 1 01/02/2021 21:09:41

其中主要字段的含义:

  • RBA: Redo Byte Address, 由三部分组成:日志序号(0x9),块编号(0x29e),块中字节偏移量(0x10)
  • LEN: Record 长度,包含头部长度
  • VLD: 头部长度标识,按照一定的逻辑计算头的长度,0x0d 就表示头部长度为 68 字节
  • SCN: System Change Number,也可称为 System Commit Number。当一个事务提交时,LOWR 将缓冲区内容写入文件,并为每个已提交的事务,分配一个标识,就是 SCN。也就是说,可以通过 SCN 跟踪数据库变化,也可以根据它决定从哪开始恢复数据。

此外,借助 SCN 还可以有针对的 dump 运行的 DML 语句,本文最后有相关的命令。

3.2 Change Vector

Record 头后面就跟着,一个或多个 Change Vector,每个 Change 都代表一个数据库操作,比如增删改,事务开始,事务回滚,事务提交等等,它的格式如下:

其中:

  • Change Header 固定 24 字节 长度
  • Length Vector 表示后面有多少个 Change Record,每 2 字节 表示一个长度,计算长度时,需要进行 4 字节对齐
  • Change Record 就是具体的变化内容了,不同的操作有不同的格式。

使用 system dump 看下 Change Header 的信息:

CHANGE #1 TYP:0 CLS:1 AFN:4 DBA:0x01000085 OBJ:73194 SCN:0x0000.000e606a SEQ:1 OP:11.2 ENC:0 RBL:0

其中主要字段的含义:

  • TYP: Change Type
  • CLS: Class 等于 X$BH.CLASS 暂时不知用途
  • DBA: Database Block Address,4字节长度,高10位表示相对文件号,低22位表示块号
  • OP: 操作码,区分操作类型,每个操作码都由两部分组成:Layer CodeSub Code,比如 11.2

下图是一些常用的操作

3.3 Transactions 事务

开始执行一个 DML 操作时,会创建一个 OP:5.2 的 Change,标识事务开始:

CHANGE #2 TYP:0 CLS:19 AFN:3 DBA:0x00c00090 OBJ:4294967295 SCN:0x0000.0010c5bb SEQ:3 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0018 sqn: 0x0000033a flg: 0x0012 siz: 108 fbi: 0
uba: 0x00c007a0.009b.40 pxid: 0x0000.000.00000000

事务提交或者回滚时,会创建一个 OP:5.4 的 Change,标识事务结束:

CHANGE #4 TYP:0 CLS:19 AFN:3 DBA:0x00c00090 OBJ:4294967295 SCN:0x0000.0010c5e6 SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0018 sqn: 0x0000033a srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00c007a0.009b.41 ext: 2 spc: 640 fbi: 0

一个完整的事务都有一个唯一标识,日志中的体现就是 XID

xid:  0x0002.018.0000033a

XID 长度是 8 字节,由三部分组成:

  • USN: Undo segment number (0x0002),目前不知如何获取此值
  • slt: Undo segment header transaction table slot (0x018),对应 ktudh/ktucm 中的 slt
  • sqn: 0x0000033a,对应 ktudh/ktucm 中的 sqn

ktudh/ktucm 中有一个 uba 字段,内容是 uba: 0x00c007a0.009b.41,它表示此 Changeundo block 中的地址,长度是 7字节,也由三部分组成:

  • undo block 的 DBA (0x00c007a0)
  • 序号 (0x009b)
  • 在 block 中的 Record 编号 (0x41)

下图是一个完整事务的示例:

执行了两个 update,其中 c1=1 的 c2 原先等于 100,更新成了 101;c1=2 的 c2 原先等于 200,更新成了 201;

4. 相关命令

4.1 日志归档和非归档

查询数据库当前的日志模式:

SQL> archive log list;
or
SQL> select log_mode from v$database;

查看在线日志:

SQL> select l.STATUS, lf.MEMBER from v$log l, v$logfile lf where l.GROUP# = lf.GROUP#;

查看已归档日志:

SQL> select recid, stamp, thread#, sequence#, name from v$archived_log;

查看默认归档路径

SQL> show parameter db_recovery_file_dest;

日志开启归档模式:

SQL> shutdown immediate;
SQL> startup mount
SQL> alter database archivelog;
SQL> alter database open;
SQL> archive log list;

日志关闭归档模式:

SQL> shutdown immediate;
SQL> startup mount
SQL> alter database noarchivelog;
SQL> alter database open;

4.2 Redo Log Dump

使用 ALTER SYSTEM 命令可以把二进制的 Redo Log 文件转储为任何文本编辑器可读的 ASCII 编码文件,有助于我们理解分析二进制结构,该命令的语法如下:

alter system dump logfile 'FileName'
scn min MinimumSCN
scn max MaximumSCN
time min MinimumTime (s)
time max MaximumTime (s)
layer Layer
opcode Opcode
dba min FileNumber BlockNumber
dba max FileNumber BlockNumber
rba min LogFileSequenceNumber BlockNumber
rba max LogFileSequenceNumber BlockNumber
objno ObjectNumber
xid UndoSegmentNumber UndoSlotNumber UndoSequenceNumber;

使用 SCN

SQL> alter system dump logfile '/u01/app/oradata/orcl/redo03.log' scn min 1099234 scn max 1099246;

使用 RBA

SQL> select cpodr_seq,cpodr_bno from x$kcccp where rownum=1;
CPODR_SEQ CPODR_BNO
---------- ----------
9 1514
SQL> DML (insert/update/delete)
SQL> select cpodr_seq,cpodr_bno from x$kcccp where rownum=1;
CPODR_SEQ CPODR_BNO
---------- ----------
9 1518 SQL> alter system dump logfile '/u01/app/oradata/orcl/redo03.log' rba min 9 1514 rba max 9 1518;

注意:每次 dump 后都需要退出此次会话,重新登录后再 dump,否则结果只会存储到一个文件内。

4.3 查询 dump 路径

有两种办法查询 dump 路径。

第一,使用以下命令查看默认路径:

SQL> show parameter user_dump_dest;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
user_dump_dest string c:\database\oracle\administrat
or\diag\rdbms\orcl\orcl\trace

第二,在执行 dump 命令前后使用以下命令,可以显示:

SQL> oradebug setmypid;
SQL> alter system dump logfile xxxxxxx
SQL> oradebug tracefile_name;
c:\database\oracle\xxxxxxx\xxxxxxx.trc

4.4 dump 一个 insert 操作

首先,查看当前使用的在线日志是哪一个,即状态为 CURRENT 的文件:

SQL> select l.STATUS, lf.MEMBER from v$log l, v$logfile lf where l.GROUP# = lf.GROUP#;

然后,往 scott 用户的 dept 表插入一条数据,查看 dump 的结果,命令如下:

SQL> select current_scn from v$database;
CURRENT_SCN
-----------
1099234
SQL> insert into scott.dept values(50, 'a', 'a');
SQL> commit;
SQL> select current_scn from v$database;
CURRENT_SCN
-----------
1099246
SQL> alter system dump logfile '/u01/app/oradata/orcl/redo03.log' scn min 1099234 scn max 1099246;

最后,二进制 Redo log dump 的结果,这里只摘出了 insert 部分,太长了,相信也没人看~~:

CHANGE #1 TYP:0 CLS:1 AFN:4 DBA:0x01000085 OBJ:73194 SCN:0x0000.000e606a SEQ:1 OP:11.2 ENC:0 RBL:0
KTB Redo
op: 0x01 ver: 0x01
compat bit: 4 (post-11) padding: 0
op: F xid: 0x0002.018.0000033a uba: 0x00c007a0.009b.40
KDO Op code: IRP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x01000085 hdba: 0x01000082
itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) size/delt: 10
fb: --H-FL-- lb: 0x1 cc: 3
null: ---
col 0: [ 2] c1 33
col 1: [ 1] 61
col 2: [ 1] 61

简单解释下,OP:11.2 表示这是一个 insert 操作;OBJ:73194 表示操作的表是 scott.dept;最后三行的 col 表示操作的字段数据,显示的数值都是 16 进制,其中 c1 33 按照一定的运算逻辑会转成 5061 就是字符 a 的 ASCII 编码。

5. 总结

建议上面的命令都手动执行下,别人总结的终究没有自己经历下,来的印象深刻。

本系列文章主要参考的有:

  • Julian Dyke 对 RedoLog 分析的 PPT
  • David Litchfield 对 Redo Logs 二进制文件剖析的 PDF
  • zhoubihui 发布在 GitHub 上的 redo_log_calculate_analysis 研究文章

以上资料网上均能搜索到,当然了,您也可以关注下wx公众号,「小创编程」回复关键字「redolog」获取。

Oracle RedoLog-基本概念和组成的更多相关文章

  1. Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)

    ORACLE集群概念和原理(二) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...

  2. 转载:【Oracle 集群】RAC知识图文详细教程(二)--Oracle 集群概念及原理

    文章导航 集群概念介绍(一) ORACLE集群概念和原理(二) RAC 工作原理和相关组件(三) 缓存融合技术(四) RAC 特殊问题和实战经验(五) ORACLE 11 G版本2 RAC在LINUX ...

  3. 【转】Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)

      阅读目录 目录 Oracle集群概念和原理 RAC概述 RAC 集成集群件管理 RAC 的体系结构 RAC 的结构组成和机制 RAC 后台进程 RAC 共享存储 RAC 数据库和单实例数据库的区别 ...

  4. 探索ORACLE之ASM概念(完整版)

    探索ORACLE之ASM概念(完整版) 本文出自https://www.jb51.net/article/43527.htm ASM是Oracle 10g R2中为了简化Oracle数据库的管理而推出 ...

  5. oracle的基本概念

    一·简介 1)数据库(DataBase) 用于存放数据,管理数据的存储仓库,是有效组织在一起的数据集合. 2)常用数据库软件 大型数据库:Oracle 中小型数据库:Mysql MySQL 3)RDB ...

  6. 浅述Oracle分布式事务概念

    着系统的复杂性不断增加,我们所面对的分布式系统渐渐增加.分布式文件系统.分布式消息队列系统等等层出不穷,在一些行业特别是互联网行业应用广泛.分布式数据库也是目前使用比较常用的分布式系统之一. 简单来说 ...

  7. Oracle包的概念

    转自:http://www.cnblogs.com/lovemoon714/archive/2012/02/29/2373695.html 1.为什么要使用包?       答: 在一个大型项目中,可 ...

  8. 转://Oracle Golden Gate 概念和原理

    引言:Oracle Golden Gate是Oracle旗下一款支持异构平台之间高级复制技术,是Oracle力推一种HA高可用产品,简称“OGG”,可以实现Active-Active 双业务中心架构 ...

  9. 全面解读Oracle同义词的概念作用、创建删除查看及Oracle的db link

    Oracle的同义词(synonyms)从字面上理解就是别名的意思,和视图的功能类似,就是一种映射关系. 在Oracle中对用户的管理是使用权限的方式来管理的,也就是说,如果我们想使用数据库,我们就必 ...

随机推荐

  1. PyQt(Python+Qt)学习随笔:PyQt界面派生类构造方法中super方法的使用

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在<第15.7节 PyQt入门学习:PyQt5应用构建详细过程介绍>和订阅专栏<第 ...

  2. 第十一章、Designer中主窗口QMainWindow类

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 主窗口对象是在新建窗口对象时,选择main window类型的模板时创建的窗口对象,如图: ...

  3. PyQt学习随笔:使用QPropertyAnimation开发简单动画

    QPropertyAnimation是PyQt5.QtCore模块提供的动画设计类,使用该类可以针对PyQt的界面对象进行动画播放,如果要针对一个指定对象进行动画播放,包括如下步骤: 一.创建动画对象 ...

  4. vue通过事件向父级组件发送消息(官网点击放大例子)

    注意:Vue.component一定要写在new Vue之前 在页面中使用组件 整体代码示例

  5. CSP-S2020复赛游记

    [本文经过删改] 前一个月 没做什么 NOIP 的题,感觉这些题对我这个做黄题封顶的人不是很友好. 前一天 考了场模拟赛,全场最低分 89,感觉信心满满. 退役那天 到了 XJ,发现没人可以面基,想着 ...

  6. mp4文件导致迅雷监视下载问题

    原因:没有为mp4设置响应的mime Type,默认就是附件的形式. 应该为其设置mime type类型  video/mp4 <staticContent> <mimeMap fi ...

  7. Element-ui 实现table的合计功能

    Element-UI是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架,其功能较为完善,根据其文档与demo学习,非常容易上手,但是我在使用其tabel组件时,发现我的功能 需求并不 ...

  8. Java各版本新增特性, Since Java 8

    Java各版本新增特性, Since Java 8 作者:Grey 原文地址: Github 语雀 博客园 Java 8 Reactor of Java 这一章来自于<Spring in Act ...

  9. 啊!Java虚方法

     什么是Java的虚方法呢,我们首先看看什么是虚函数 虚函数 百度百科的解释为: 在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的[成员函数],用法格式为:virtual 函数返回 ...

  10. centos7安装Hive及其问题解决

    本地如何安装hive (安装hive之前需要安装hadoop并启动hadoop的相关集群,mysql数据库) hadoop集群是两台,一台作为master,两台作为slaver,mysql单独占用一台 ...