zoukankan      html  css  js  c++  java
  • Oracle RedoLog-二进制格式分析,文件头,DML,DDL

    上篇文章,简单介绍了 RedoLog 是什么,以及怎么从 Oracle Dump 二进制日志。接下来,分析下 Redo Log 二进制文件的格式,主要包括:文件头重做日志头DML-INSERT 操作DDL-CREATE 操作

    Redo Log 二进制文件中,采用的是小端序字节序。

    原文链接:https://www.chuonye.com/archives/oracle-redolog-format.html

    1. File Header

    文件头,占用第一个块。Oracle 中许多二进制的数据和日志文件都有相似的格式,在线日志 Redo Log 文件也是如此。下图是 RedoLog 文件开始的前 80 字节。

    file-header

    File Type

    2字节 表示文件类型,区分不同的 Oracle 文件,比如,在 10g 版本中:

    • 0xA2 表示数据文件,Data File
    • 0xC2 表示控制文件,Control File
    • 0x22 表示重做日志文件,Redo Log File

    Oracle 数据库其实就是由一堆文件组成的。

    Block Size

    偏移量 20,长度 2字节,存储的是块大小,它的值是固定的,只会因操作系统而不同。在 Windows, Linux 和 Solaris 上,块大小为 512字节–0x0200,而 HP-UX 的块大小为 1024。

    另外,每个块都有一个 16字节 的块头,稍后会介绍它。

    Number of Blocks

    偏移量 24,长度 4字节,存储的是文件中的块数,不包括文件头本身使用的块,可以这样计算出整个文件的大小:

    (0x00019000 + 1) * 512 = 52429312 (50MB)
    

    Magic

    魔数只是文件标识,用来检查是否是 Oracle 文件。

    Block Header

    每个块都有一个 16字节 的头部,即使一个 Redo Record 横跨多个块,解析时这一点尤为重要。

    block-header

    上图黄色指示的是一个头部示例,每个块头都是以签名 0x0122 开头,其中:

    • 偏移量 4,长度 4字节,存储的是块在文件中的编号
    • 偏移量 8,长度 4字节,存储的是日志序号
    • 偏移量 12,长度 1字节,存储的是 Record 在该块内的字节偏移量

    这三个值正好是 Record 的 RBA 内容。

    最后偏移量 14,长度 2字节,存储的是校验和,用于验证数据是否完整,验证的逻辑这里就不记录了,感兴趣的可以在上篇描述的 PDF 文件内找到。

    2. Redo Log Header

    重做日志头,占用第二个块。这里包含的信息就多了,如数据库SID,数据库版本和开始记录的时间等。

    redolog-header

    3. Redo Record

    Redo Record 包含一个 SCN 中的所有操作,由一个头和一个或多个 change vector 组成。比如往一个有索引的表中插入一条数据,会创建以下内容:

    • 为 INSERT 操作,分别创建 redo changeundo change
    • 为索引改动,分别创建 redo changeundo change
    • 一个事务开始 change,一个事务提交 change

    其中的每个 Change 都有一个操作码,用于区分,常见的操作码:

    • 5.1:撤销修改 - Undo Record
    • 5.2:事务开始
    • 5.4:事务提交 - Commit
    • 11.2:插入一行数据
    • 11.3:删除一行数据
    • 11.11:插入多行数据
    • 11.19:更新多行数据
    • 10.2:插入一个索引 - INSERT LEAF ROW
    • 10.4:删除一个索引 - DELETE LEAF ROW
    • 13.1:申请空间 - CREATE TABLE 后
    • 24.1:DDL 操作

    4. DML-INSERT

    增删改是数据库基本操作,下图显示的是一个插入操作 Record 转成十六进制的信息。

    redolog-header

    Block 头的第 12 个字节 0x10,表示 Record 开始字节在偏移量 16字节 处;

    Record 开始的前 2字节 表示长度,最大为 65536字节,因此它可能需要多个 block 存储。这里长度是 0x01A8=424 一个 block 足以存储。之后的第4个字节是 Record 头长度标识 VLD,具体数值取决于 Record 类型,这里的 0x0D 表示头长度为 0x44=68

    跳过 0x44字节 就能找到第一个 Change Vector,操作码是 0x0B02 - 11.2,即 INSERT 操作。在操作码后的第22字节,可以找到插入对象的ID,这里是 0x0057 - 87,在字典表 dba_objects 查询 data_object_id=87 的记录可知插入的表为 SYS.SYSAUTH$

    跳过 0x44+0x18字节,开始的2字节 0x000C=12 表示第一个 Change 的元素长度列表的长度,元素长度占用 2字节,12字节表示除头2字节外,总共有 (12-2)/2=5 个 长度元素,这意味着插入了 3个 字段内容。

    • 0x00140x0031:这两个值是半固定的,表示 KTBKDO 的长度
    • 0x0002:表示插入第一列的数据字节数为 2字节
    • 0x0002:表示插入第二列的数据字节数也为 2字节
    • 0x0003:表示插入第三列的数据字节数为 3字节

    上面的长度计算的是实际长度,但在计算偏移量是都需要 4字节对齐。跳过指定的字节后,可以得到三个字段的值为:

    • 0xC102:表示的内容为 数字 1
    • 0xC105:表示的内容为 数字 4
    • 0xC20931:表示的内容为 数字 848

    结合 SYSAUTH$ 的字段就能还原 SQL:

    SQL> INSERT INTO SYS.SYSAUTH$ (GRANTEE#,PRIVILEGE#, SEQUENCE#) VALUES (1,4,848); 
    

    再往后有两个 Change,0x05020x05010x0502 可以解析出此次事务的 XID0x0501 是撤销操作,INSERT 对应的就是 DELETE。

    5. DDL-CREATE

    虽然 DDL 语句已写入 Redo Log 文件中,但是在使用 ALTER SYSTEM DUMP LOGFILE 命令后,结果中没有语句,内容如下:

    REDO RECORD - Thread:1 RBA: 0x000082.0000febf.002c LEN: 0x00f4 VLD: 0x01 
    SCN: 0x0000.003a061f SUBSCN:  1 03/13/2007 13:55:41 
    CHANGE #1 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ:  0 OP:24.1 
    

    操作码 24.1 表明是 DDL 操作。从 RBA 中,可以看到块编号为 0x0000febf (65215),块大小为 512,所以该操作在二进制文件的偏移量为 512*65215=33390080 ,十六进制为 0x01FD7E00

    ddl-location

    可以清楚的看到 DDL 语句:

    create user wiggywiggywiggy identified by VALUES '2FA1749D698AD874'
    

    对应二进制格式映射信息是:

    ddl-format

    6. 总结

    本文简单描述了二进制格式具体是什么,实际分析的时候也是这样,把二进制文件打开转成 16进制显示,一个字节一个字节的分析。如果做过网络编程,特别是 TCP 私有协议设计和解析,应该很容易理解。

    下一篇会介绍解析的一些问题,比如 Record 头长度怎么计算,Rowid 怎么计算等等。

  • 相关阅读:
    快速幂求模
    elasticSearch入门
    springboot 停止
    gson
    jetty 入门
    redis工具
    oracle数据库操作
    Spring事务控制和回滚
    SPI
    PLSQLDeveloper_免安装自带client
  • 原文地址:https://www.cnblogs.com/chuonye/p/14248895.html
Copyright © 2011-2022 走看看