本文主要介绍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