【REDO】Oracle redo内部结构

本文主要介绍Oracle redo log结构学习,整理归纳。 —By Firsouler

1.概述

重做日志包含数据库所有数据产生的历史改变记录,其通常用于
  • 恢复(实例恢复和介质恢复)
  • 日志挖掘
数据库产生的每个改动:
  • 写入数据库缓冲之前,先写入重做日志 —内存
  • 写入数据文件之前先写入日志文件 —数据文件
当提交后,日志缓冲被刷入重做文件里
对于每个改动,服务器进程:
  • 数据块buffer被钉为排它模式;
  • 在pga里构造改变向量
  • 在PGA构造redo条目
  • 在log buffer里确定需要的空间
  • 在log buffer里分配空间
  • 在buffer cache更改数据块
重做日志文件
  • 包含所有 由DML 语句产生的更改
  • 不包含 DML 语句文本
  • 包含所有DDL语句造成的数据字典对象的更改
  • 包含 DDL 语句文本
  • 包含所有递归语句的更改

2.日志文件

  • 日志文件使用操作系统块大小(512bytes),格式依赖于操作系统、Oracle版本
  • redo日志组成: 数据头、Redo记录、Redo记录、Redo log 循环写
Block 0 block 1 block 2 block 3 Block N
文件头 redo 头 Redo记录1 Redo 记录2/3 Redo记录N
Redo 记录
  • redo 记录包括: redo记录头、一个或多个改变向量
  • 每个redo记录包含每个原子改变的undo和redo
  • 某些改变不需要undo

Redo Record header | change #1 | change #2 |… |Change #N

Redo记录头
--分析redo
oradebug setmypid
oradebug unlimit
alter system dump logfile '+DATA/mydb/onlinelog/group_2.266.1018473579'
--dba min 5 5 dba max 5 10;
--scn min 7518013947 scn max 7518013970;
oradebug tracefile_name
REDO RECORD - Thread:1 RBA: 0x0001e5.000067c3.00e4 LEN: 0x0048 VLD: 0x01
SCN: 0x0000.01a6059e SUBSCN:178 01/10/2021 18:07:52
#Thread :线程数
RBA :Redo 字节地址
LEN:记录长度(bytes)
SCN: 系统改变号
改变时间
Redo Byte Address (RBA):

10字节长,它确定起始redo记录,字段,log序列号.redo日志里的块号.块里的字节号

系统改变号 (SCN):

wrap(2字节).base(4字节)

base是每个新scn的增长数,保存在redo记录的头部

rac维护一个全局的,分布式事务用最高的scn

改变向量
  • 定义单个数据块的改变
  • 能应用于:undo头、undo数据块、数据段头、数据块
  • 数据块缓存被更改之前在pga里创建
  • 包含:头部、改变记录长度数组、改变记录数组
CHANGE #2 TYP:0 CLS: 1 AFN:5 DBA:0x0144d023 SCN:0x0000.0ac67cce SEQ:  4 OP:11.5
#change: 改变数
#typ:改变类型
#cls:类
#afn:绝对文件号
#dba:相对数据块块地址
#scn:系统改变号
#seq:序列号(相对于scn)
#op:操作代码

改变头部类与 X$BH.CLASS一样:
Class | Description
—- | —-
1 |数据块
2 |排序块
3 |延迟undo段块
4 |段头块(表)
5 |延迟undo段块
6 |Free List块
7 |区映射块
8 |空间管理位置块
9 |空间管理索引块
10 |未使用的
11+2r |为undo段r准备的段头
12+2r |为undo段r准备的数据块

数据块地址

每个数据库都有一个DBA,DBA为4 bytes,域为:高位10bits代表相对文件号,低位22 bits代表块号,如:

DECLARE
l_dba  NUMBER := TO_NUMBER ('0144D023','XXXXXXXX');
l_file NUMBER := DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE (l_dba);
l_block    NUMBER := DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK (l_dba);
BEGIN 
    DBMS_OUTPUT.PUT_LINE ('File  : '||l_file);
    DBMS_OUTPUT.PUT_LINE ('Block : '||l_block);
END;
操作代码
  • 每个改变代表着在redo日志里的一个操作
  • 有超过150个不同的操作
  • 每个操作有个层级代码和一个子代码如11.2
  • 层级代码包括:
层级 描述 层级 描述
4 块清除 18 块映像(热备)
5 事务管理 19 直接路径装载
10 索引操作 20 兼容段
11 行操作 22 本地管理表空间
13 段管理 23 块写
14 区管理 24 DDL语句
17 表空间管理
事务

会话的第一个DML语句是创建一个事务:分配undo段,创建一个5.2改变,用于更新undo段头里的事务表

CHANGE #1 TYP:0 CLS:25 AFN:3 DBA:0x00c0012e SCN:0x0000.0ac86eb8 SEQ:  1 OP:5.2 ktudh redo: slt: 0x0010 sqn: 0x0000475a flg: 0x0012 siz: 96 fbi: 0 uba: 0x00c04d20.234b.0e    pxid:  0x0000.000.00000000
  • 提交或hung终结事务
  • 5.4改变是创建一个提交点
CHANGE #1 TYP:0 CLS:25 AFN:3 DBA:0x00c0012e SCN:0x0000.0ac86ebf SEQ:  1 OP:5.4
ktucm redo: slt: 0x0010 sqn: 0x0000475a srt: 0 sta: 9 flg: 0x0
  • 提交后紧接着为事务回滚应用所有回滚
事务ID(XID)
xid:  0x0004.00e.0000449b
  • 每个事务有一个id
  • xid为8bytes
  • 包含:事务回滚段编号(USN).回滚段头事务表slot.序列号(wrap)
回滚块地址 (UBA)
uba: 0x00c01f17.2758.04
  • UBA 7bytes
  • 包括 回滚块的DBA.序列号.块里的记录号

可以做下重做日志转储测试

行操作
代码 助记 描述
11.2 IRP 插入单行
11.3 DRP 删除单行
11.4 LKR 锁定行
11.5 URP 更新行
11.6 ORP 行链接
11.9 CKI 簇键索引
11.10 SKL 设置簇主键指针
11.11 QMI 插入多行
11.12 QMD 删除多行
索引操作

代码包括(10):

Opcode Description Opcode Description
10.2 插入叶行 10.13 清空叶块
10.3 清除(Purge)叶行 10.15 插入枝行
10.4 删除(Delete)叶行 10.16 清除(Purge)枝
10.5 恢复叶日志 10.18 更新行主键值
10.6 锁数据块 10.19 清除分裂标志
10.7 提交时清除块操作代码 10.21 回滚分支操作
10.8 初始头部 10.22 回滚叶操作
10.9 ITL 1应用 XAT 10.24 收缩 ITL
10.1 设置叶块的下一个指针 10.3 更新非主键值
10.11 设置叶块的前一个指针 10.31 创建或加载索引
10.12 分裂后初始根块 10.34 清空叶块(?)
块清除

发送条件:当提交更改时,数据块的itl没有被更新
块清除重做:能在select语句时产生、操作代码为4.1,、每块需要60 byte重做记录

备份
  • 为每个被修改的数据块的块映相被写入重做日志(操作代码18.1)
  • 备份被取消时,一个备份结束标志被写进重做日志(17.1)

转储日志文件

--指定数据库范围
alter system dump logfile '' dba min   dba max  ;
--指定rba范围
ALTER SYSTEM DUMP LOGFILE ' ' RBA MIN   RBA MAX  ;
--指定层次代码和操作代码:
ALTER SYSTEM DUMP LOGFILE ' ' layer  opcode 

参考:

1. https://www.shangmayuan.com/a/5272c7f59496453995998f87.html
2.www.juliandyke.com

请使用浏览器的分享功能分享到微信等