oracle实例恢复时,哪些redo是需要重做的?

举报
dayu_dls 发表于 2021/05/21 10:14:46 2021/05/21
【摘要】 说一下oracle实例恢复时,要用到哪些redo。至于何时需要实例恢复就不多说了。我们都知道实例恢复时,需要找到redo的起点(lrba,也就是checkpoint rba:检查点队列中第一脏块的lrba)和终点(on-disk rba)。终点自然就是redo的结尾,起点就比较麻烦了。检查点队列头部的那个脏块第一次被修改对应的日志位置就是lrba,在这个lrba之前的redo所保护的data...

说一下oracle实例恢复时,要用到哪些redo。至于何时需要实例恢复就不多说了。

我们都知道实例恢复时,需要找到redo的起点(lrba,也就是checkpoint rba:检查点队列中第一脏块的lrba)和终点(on-disk rba)。终点自然就是redo的结尾,起点就比较麻烦了。检查点队列头部的那个脏块第一次被修改对应的日志位置就是lrba,在这个lrba之前的redo所保护的data buffer都已经被写入到磁盘。由于lrba记录的是脏块第一次被修改对应的日志位置,这就是说在检查点队列中当这个buffer被写入磁盘时,这个buffer可能被可能被修改多次,对应着多条redo条目。增量检查点更新控制文件中的lrba后,而这些redo可能会存在lrba之后,然而这些redo所保护的buffer已经写入到磁盘,必然是不需要再重做的。说起来比较绕口,下面看个图吧。

更新table表中的记录,记录行的数据块分布及产生的日志信息如下:

  Update table set name=low(name) where id=1; ------RBA 692.2998.10
  Update table set name=low(name) where id=2; ------
1 RBA 692.3015.10
  Update table set name=low(name) where id=4; ------
2 RBA 692.3024.10
  Update table set name=low(name) where id=7; ------
3 RBA 692.3033.10
  Update table set name=low(name) where id=3; ------
1 RBA 692.3102.10
  Update table set name=low(name) where id=10; ------
4 RBA 692.3127.10

  Update table set name=low(name) where id=13; ------5 RBA 692.3136.10

data buffer中checkpoint queue大概就是下面这样:

1号块 2号块 3号块 4号块 5号块

lLRBA:692.2998.10

HRBA:692.3102.10

LRBA:692.3024.10

HRBA:692.3024.10

LRBA:692.3033.10

HRBA:692.3033.10

LRBA:692.3127.10

HRBA:692.3127.10

LRBA:692.3136.10

HRBA:692.3136.10


相应的重做记录有:

RBA692.2998.10(第一条更新命令对应的重做记录)

回滚段头重做信息

回滚段块重做信息

1号块第1行重做信息

(下面的重做记录中省略具体的信息)

RBA692.3015.10 (第二条更新命令对应的重做记录)

RBA692.3024.10 (第三条更新命令对应的重做记录)

RBA692.3033.10 (第四条更新命令对应的重做记录)

RBA692.3102.10 (第五条更新命令对应的重做记录)

RBA692.3127.10 (第六条更新命令对应的重做记录)

RBA692.3136.10 (第七条更新命令对应的重做记录)

现在开始发生增量检查点,dbwr进程开始从检查点队列写数据,假设现在1号、2号被写入,3号块的lrba被更新到控制文件中,一次增量检查完成。数据库突然断电需要实例恢复,从控制文件中找到lrba,开始重做redo到结束。那么显然第5行日志是不需要再做的,因为这条日志所保护的数据已经在上一次增量检查点发生时被写入到磁盘。那么oracle会怎么判断这条日志要不要做呢?

我们知道redo中会记录每个redo record的scn和rba。scn指的是redo产生时当前数据库的时间,如下图:

REDO RECORD - Thread:1 RBA: 0x000040.00000024.01b4 LEN: 0x00e4 VLD: 0x01

SCN: 0x0000.0075933b SUBSCN:  7 02/08/2018 14:10:00

CHANGE #1 TYP:0 CLS:26 AFN:3 DBA:0x00c00b4e OBJ:4294967295 SCN:0x0000.0075933b SEQ:6 OP:5.1 ENC:0 RBL:0

ktudb redo: siz: 88 spc: 3666 flg: 0x0022 seq: 0x066c rec: 0x25

            xid:  0x0005.020.000012bb

ktubu redo: slt: 32 rci: 36 opc: 10.22 objn: 6035 objd: 6040 tsn: 0

Undo type:  Regular undo       Undo type:  Last buffer split:  No

Tablespace Undo:  No

             0x00000000

index undo for leaf key operations

KTB Redo

op: 0x02  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: C  uba: 0x00c00b4e.066c.24

Dump kdilk : itl=2, kdxlkflg=0x1 sdc=0 indexid=0x403100 block=0x00403101

(kdxlpu): purge leaf row

key :(15):  07 78 76 02 08 08 0b 01 06 00 41 24 fc 00 08

CHANGE #2 TYP:0 CLS:1 AFN:1 DBA:0x00403101 OBJ:6040 SCN:0x0000.0075933b SEQ:2 OP:10.2 ENC:0 RBL:0

index redo (kdxlin):  insert leaf row

KTB Redo

op: 0x02  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: C  uba: 0x00c00b4e.066c.25

REDO: SINGLE / -- / --

itl: 2, sno: 29, row size 19

insert key: (15):  07 78 76 02 08 08 0b 01 06 00 41 24 fc 00 08


把数据块dump下来,数据块上记录着上一次增量检查点时,哪些redo保护的数据被写入到磁盘。即lscn与hscn之间的redo。

Start dump data blocks tsn: 0 file#:1 minblk 77057 maxblk 77057

Block dump from cache:

Dump of buffer cache at level 4 for tsn=0 rdba=4271361

BH (0xecff7048) file#: 1 rdba: 0x00412d01 (1/77057) class: 1 ba: 0xecf16000

  set: 11 pool: 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 659,28

  dbwrid: 0 obj: 96602 objn: 96602 tsn: 0 afn: 1 hint: f

  hash: [0x136ae98a8,0x136ae98a8] lru: [0xecff7270,0xedfbf788]

  ckptq: [NULL] fileq: [NULL] objq: [0x121ef05a8,0x121ef05a8] objaq: [0x121ef0598,0x121ef0598]

  st: XCURRENT md: NULL fpin: 'ktswh23: ktsfbkl' tch: 2

  flags: block_written_once redo_since_read

  LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [1]

Block dump from disk:

buffer tsn: 0 rdba: 0x00412d01 (1/77057)

scn: 0x0000.0076b969 seq: 0x01 flg: 0x06 tail: 0xb9690601

那么我们上面的问题就迎刃而解了。实例恢复的步骤:

①读取控制文件获取lrba,确定恢复所需的redo范围;

②redo重做,判断该行日志的scn与数据块hscn的大小,只有在hscn之后的redo才会被重做,之前的redo保护的数据已经写入磁盘,不需要再做。

上面数据块的dump文件是我在手动checkpoint之后的,发现lscn为0,hscn为无穷大。也刚好证明了上面所说,checkpoint之后所有的脏数据写入磁盘,检查点队列为空。即使实例恢复,对于该块来说也没有redo需要重做。因为在hscn之后不存在该块的redo。如果你的lscn和hscn信息如上面所示,证明这个块的所有脏数据已经被写入磁盘。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。