书名

临危不惧:Oracle 11g数据库恢复技术

作者

包光磊

简介

《临危不惧:Oracle 11g数据库恢复技术》分为三大部分:恢复的原理、恢复的工具、恢复的具体步骤与实战。第一部分能够让读者领略恢复操作的本质,是其他部分的理论基础,包括“重做日志”、“控制文件”、“补充日志”;第二部分详细地介绍了备份/恢复数据库的工具,包括恢复管理器、恢复编录和数据泵;第三部分以各种数据库损毁场景为例,每一章解决一组特定的问题,其中:第7~11章讨论各种文件(控制文件、数据文件等)遭到不同程度的破坏后,数据库的行为特征及如何将其恢复;第12章探讨如何将数据库恢复至以前的时间点;第13章讨论如何处理各种数据库文件在没有备份时受损的情况;第14章全面介绍了用于恢复人为错误的各种闪回技术:第15章介绍将恢复的单位缩小,精确到数据块级别,以提高恢复效率;第16章介绍一种非常规恢复的方法一挖掘日志。

Oracle11g数据库恢复技术_读书笔记_第1章 重做日志(Redo Log)_重做

第1章 重做日志(Redo Log)

Oracle数据库三大核心文件:数据文件、重做日志(在线和归档)、控制文件

5个关键概念

  • RBA(Redo Byte Address,重做字节地址)
  • SCN(System Change Number,系统变更号)
  • DBA(相对数据块地址)
  • 数据块版本号(SCN+SEQ)
  • Checkpoint(检查点)

重做记录

对数据库任何形式的更改,都会在更改操作之前产生一条重做记录。

重做记录包含一个或多个变更矢量(Change Vector),变更矢量保证了数据块在修改前后的一致性,重做记录保证了数据库在修改前后的一致性。

  • SCN:Oracle表示时间流逝的一种方式,一个数据库只有一个全局的SCN产生器,数据库中任何变更(包括访问控制文件),SCN都会增加,即使没有任何变更,每3秒也至少加1。数据块头部信息记录了SCN,可能存在多条重做记录的SCN相同,此时用SUBSCN来区分,SUBSCN又称SEQ,SCN+SEQ就是数据块版本号,SCN占6字节,SEQ占1字节。
  • SCN理论最大值为0xffff.ffffffff,即1612,用10进制表示为281474976710655,用尽后会循环到最小值。

SCN+SEQ信息同时出现在重做日志和数据文件中。如"SCN:0x0000.000FD122 SUBSCN:1"。

#查询v$database等同于访问控制文件,每次查询都会生成一个新的SCN
select current_scn from v$database;

#如果想查询当前的SCN而不是产生一个新的SCN,应该使用以下查询
select dbms_flashback.get_system_change_number from dual;
  • RBA:由4部分组成:日志线程号、日志序列号、日志文件块编号、日志文件块字节偏移量,占10字节。

如"Thread:1 RBA:0x000025.00000003.0010"

表示在1号线程37号序列号重做日志文件的第3个块中的第16个字节处。

  • BASE64转换表

索引

对应字符

索引

对应字符

索引

对应字符

索引

对应字符

0

A

17

R

34

i

51

z

1

B

18

S

35

j

52

0

2

C

19

T

36

k

53

1

3

D

20

U

37

l

54

2

4

E

21

V

38

m

55

3

5

F

22

W

39

n

56

4

6

G

23

X

40

o

57

5

7

H

24

Y

41

p

58

6

8

I

25

Z

42

q

59

7

9

J

26

a

43

r

60

8

10

K

27

b

44

s

61

9

11

L

28

c

45

t

62

+

12

M

29

d

46

u

63

/

13

N

30

e

47

v

14

O

31

f

48

w

15

P

32

g

49

x

16

Q

33

h

50

y

sqlplus sys/oracle@testdb as sysdba
set line 500;
select rowid,salary,first_name,last_name from hr.employees where employee_id=100;


ROWID                SALARY      FIRST_NAME                    LAST_NAME
-----------------   ----------  ----------------------------  -------------------------
AAAXZ5AAEAAAAD7AAA   24000       Steven                        King

rowid(AAAXZ5AAEAAAAD7AAA)查询BASE转换表手工解析:

前6位AAAXZ5代表 OBJECT_ID 23*642+25*641+57*640=95865

接下来3位AAE代表 数据文件号 4*640=4

接下来6位AAAAD7代表 数据块编号 3*641+59*640=251

接下来3位AAA代表 行编号 0*640=0

SELECT
    DBMS_ROWID.ROWID_OBJECT(ROWID) AS object_id,
    DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) AS file_number,
    DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) AS block_number,
    DBMS_ROWID.ROWID_ROW_NUMBER(ROWID) AS row_number
FROM
     hr.employees where employee_id=100;


 OBJECT_ID FILE_NUMBER BLOCK_NUMBER ROW_NUMBER
---------- ----------- ------------ ----------
     95865           4          251          0
  • 转储重做日志文件信息
#启用最小补充日志
alter database add supplemental log data;

#切换redo日志
alter system switch logfile;

#查询redo日志信息
select lg.group#,lg.sequence#,lgf.member,lg.status 
from v$log lg,v$logfile lgf where lg.group#=lgf.group#;

#查询数据行信息 file_id,block_id,rowid
select dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowid) block_id,rowid,
employees.salary from hr.employees where employee_id=100;

   FILE_ID   BLOCK_ID ROWID                  SALARY
---------- ---------- ------------------ ----------
         4        251 AAAXZ5AAEAAAAD7AAA      24000
         

#执行update更新数据
update hr.employees set salary=salary*1.2 where employee_id=100;

#转储重做日志文件
alter system dump logfile '/u01/data/HISDB/onlinelog/o1_mf_11_m3p4mk7m_.log' dba min 4 251 dba max 4 251; 
#ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME REDOHDR LEVEL 10';

#查看转储文件路径
select value from v$diag_info where name='Default Trace File';

update操作产生的变更矢量(redo日志中)

  • CHANGE#1 AFN:3,DBA:0x00c00080,记录修改前的SCN+SEQ
  • CHANGE#2 AFN:3,DBA:0x00c0172e,在3号文件(undo)的5934号数据块中记录修改前的值:第1行第8个字段,修改前的值为c30329
  • CHANGE#3 AFN:4,DBA:0x010000fb,记录修改4号文件251号数据块第1行第8个字段,修改值为c30359
  • CHANGE#4 没有更改意图

update的目的是修改4号文件251号数据块(CHANGE #3),但是必须先在3号文件128号块注册事务表(CHANGE #1),并在事务表中的3号文件5934号数据块中保存撤销数据(CHANGE #2)保证事务可以被回滚

# CHANGE#1 12583040 为DBA 0x00c00080 转换成10进制的数值  
select dbms_utility.data_block_address_file(12583040) as rfile,
dbms_utility.data_block_address_block(12583040) as block from dual;

     RFILE      BLOCK
---------- ----------
         3        128


# CHANGE#2 12588846 为DBA 0x00c0172e 转换成10进制的数值
select dbms_utility.data_block_address_file(12588846) as rfile,
dbms_utility.data_block_address_block(12588846) as block from dual;

     RFILE      BLOCK
---------- ----------
         3       5934
         

# CHANGE#2 16777467 为DBA 0x010000fb 转换成10进制的数值
select dbms_utility.data_block_address_file(16777467) as rfile,
dbms_utility.data_block_address_block(16777467) as block from dual;

     RFILE      BLOCK
---------- ----------
         4        251


select file#, name from v$datafile; 

     FILE# NAME
---------- -------------------------------------------
         1 /u01/data/hisdb/system01.dbf
         2 /u01/data/hisdb/sysaux01.dbf
         3 /u01/data/hisdb/undotbs01.dbf
         4 /u01/data/hisdb/users01.dbf



SELECT DUMP(24000,16) FROM DUAL;

DUMP(24000,16)
----------------------------------------
Typ=2 Len=3: c3,3,29


SELECT DUMP(28800,16) FROM DUAL;

DUMP(28800,16)
----------------------------------------
Typ=2 Len=3: c3,3,59

Oracle11g数据库恢复技术_读书笔记_第1章 重做日志(Redo Log)_检查点_02

show parameter log_buffer;

LGWR将缓冲区数据写入在线重做日志的条件:

  • 每隔3秒
  • 日志缓冲区数据超过1MB
  • 日志缓冲区数据达到1/3容量
  • 执行commit
  • 在DBWn进程中将脏数据块写入数据文件之前

在线重做日志

每组在线重做日志建议至少配置2个成员,互为镜像,其中1个成员文件故障并不影响oracle的启动和正常运行,但是在日志中会有告警记录。

trace路径:$ORACLE_BASE/diag/rdbms/hisdb/hisdb/trace

假设一个数据库操作产生的重做记录为R,脏数据块(存在 Database Buffer Cache 中)为D,在LGWR没有把R写入在线重做日志文件的情况下,Oracle是不允许DBWn将D写入数据文件的。所以在数据库打开的情况下,数据文件永远比重做日志文件旧。

检查点

检查点的目的是将检查点目标(某条重做记录及其头部的RBA和SCN)写入数据文件和控制文件。

参与检查点的进程包括LGWR、DBWn、CKPT

检查点分为完全检查点和增量检查点

完全检查点

  • 在日志缓冲区中提取最新的重做记录的RBA和SCN作为检查点目标
  • LGWR清空日志缓冲,将其写入在线日志
  • DBWn将检查点目标(RBA和SCN)及之前的所有脏数据按RBA顺序写入数据文件
  • CKPT将检查点目标(RBA和SCN)写入数据文件头部和控制文件

完全检查点发生时机

  • shutdown immediate (高优先级,立即完成)
  • alter system checkpoint (高优先级,立即完成)
  • alter system switch logfile (低优先级,延迟几分钟完成,查看alert日志)
Fri May 10 04:24:48 2024
Beginning log switch checkpoint up to RBA [0x1b.2.10], SCN: 1030971
Thread 1 advanced to log sequence 27 (LGWR switch)
  Current log# 3 seq# 27 mem# 0: /data/itpuxdb/redo03.log
Fri May 10 04:27:23 2024
Completed checkpoint up to RBA [0x1b.2.10], SCN: 1030971
  • 维护表空间操作时 (不完整,仅将特定表空间的脏数据块写回数据文件)
#修改初始化参数
alter system set log_checkpoints_to_alert=TRUE;

#创建完全检查点
alter system checkpoint;

Fri May 10 04:18:07 2024
Beginning global checkpoint up to RBA [0x19.22b.10], SCN: 1030819
Completed checkpoint up to RBA [0x19.22b.10], SCN: 1030819
#表示25号重做日志555号日志块中的第16字节,SCN为1030819

#查询最近一次已完成的完全检查点SCN
select file#,checkpoint_change# from v$datafile_header;

#查询数据文件的检查点SCN
select file#,name,checkpoint_change# from v$datafile;

增量检查点(由Oracle自动控制)

  • 确定一条非最新重做记录的RBA和SCN作为检查点目标(小于在线日志大小总和与最大在线日志大小差的0.9倍,假设有3组重做日志,每组大小为1G,则计算公式为(3-1)*0.9=1.8G,增量检查点的RBA距离当前最新的RBA的“距离”不能大于1.8G)
  • LGWR清空日志缓冲,将其写入在线日志
  • DBWn将检查点目标(RBA和SCN)及之前的所有脏数据按RBA顺序写入数据文件
  • CKPT将检查点目标(RBA和SCN)写入控制文件

增量检查点存在的意义:减少发生完全检查点时DBWn的工作负担,提高实例恢复的速度

实例恢复

数据库正常关闭时会发起完全检查点,此时停止任何更新,LGWR将日志缓冲区数据写入在线重做日志,DBWn将脏数据块写入数据文件,数据文件与在线重做日志文件正真同步。每次打开数据库时Oracle都会执行该检查。

数据库异常关闭时,如断电、shutdown abort,Oracle没来得及完成完全检查点,数据文件比在线重做日志文件要旧,下一次打开数据库时,同步测试无法通过,此时如果控制文件、数据文件、在线重做日志文件都没有损坏,Oracle会自动发起实例恢复的操作同步数据文件,并且在告警日志中留下以下痕迹:

ALTER DATABASE OPEN
Beginning crash recovery of 1 threads
 parallel recovery started with 3 processes
Started redo scan
Completed redo scan
 read 62 KB redo, 39 data blocks need recovery
Started redo application at
 Thread 1: logseq 31, block 3
Recovery of Online Redo Log: Thread 1 Group 1 Seq 31 Reading mem 0
  Mem# 0: /data/itpuxdb/redo01.log
Recovery of Online Redo Log: Thread 1 Group 2 Seq 32 Reading mem 0
  Mem# 0: /data/itpuxdb/redo02A.log
  Mem# 1: /data/itpuxdb/redo02B.log
Recovery of Online Redo Log: Thread 1 Group 3 Seq 33 Reading mem 0
  Mem# 0: /data/itpuxdb/redo03.log
Completed redo application of 0.04MB
Completed crash recovery at
 Thread 1: logseq 33, block 2, scn 1074188
 39 data blocks read, 39 data blocks written, 62 redo k-bytes read

数据库异常关闭后再启动恢复时步骤:

  1. startup
  2. 打开参数文件
  3. 打开控制文件
  4. 检查数据文件和日志文件是否同步
  5. 前滚重做日志中所有记录
  6. 数据库即可打开接收客户端请求
  7. 回滚没有提交的事务

两次读取法(仅在实例恢复时使用):书本第18页

select lg.group#,lg.sequence#,lg.status,lf.member
,to_char(first_time,'YYYY-MM-DD HH24:MM:SS') AS first_time
from v$log lg inner join v$logfile lf on lg.group#=lf.group#;
  • CURRENT 表示当前正在使用的,是实例恢复需要的
  • ACTIVE 最近一次完全检查点的RBA、SCN小于该日志中最后一条重做记录的RBA和SCN,是实例恢复需要的
  • INACTIVE 最近一次完全检查点的RBA、SCN大于该日志中最后一条重做记录的RBA和SCN,是实例恢复不需要的

如果LGWR的下一个日志状态是ACTIVE,则LGWR会被挂起,Oracle自动发起一个高优先级的完全检查点,完成后日志状态会从ACTIVE变成INACTIVE,此时LGWR才能覆盖写入该日志。

归档日志

归档日志是在线重做日志的备份,由ARCn在LGWR覆盖在线重做日志之前复制而来,在数据库启动时不会被打开,没有维护的情况下数量会不断增加,主要作用是支持介质恢复和RMAN在线备份。

archive log list;
select log_mode from v$database;

#开启归档
alter database archivelog;

#查询归档信息
select sequence#,first_change#,next_change#,name from v$archived_log;

#设置归档路径为/data/arch
alter system set log_archive_dest_1='location=/data/arch';

#设置归档文件格式  (保存在快速恢复区时有另外的命名规范,不受此参数控制)
alter system set log_archive_format='arc_hisdb_%t_%s_%r' scope=spfile;

归档日志路径(优先级从上至下,上面的缺省则使用下面的)

  1. log_archive_dest_N参数
  2. db_recovery_file_dest参数指向的快速恢复区
  3. $ORACLE_HOME/dbs

修改初始化参数log_archive_max_processes可以启动多个ARCn进程(最多30)

介质恢复

与实例恢复的区别是实例恢复没有文件损坏,知识文件不同步(数据文件比日志文件旧),而介质恢复是有文件损坏,将其还原、恢复的过程。

recover automatic datafile 1;
#第26页

★日志转储

#转储指定数据块修改的重做记录(4号数据文件中251-260号数据块)
alter system dump logfile '/extend/oradata/hisdb/redo01A.log' dba min 4 251 dba max 4 260; 
#转储指定RBA(22号日志中10-20号块)日志文件的块大小和数据文件的块大小不一样
alter system dump logfile '/extend/oradata/hisdb/redo01A.log' rba min 22 10 rba max 22 20;

#转储指定SCN号(123456)的重做记录
alter system dump logfile '/extend/oradata/hisdb/redo01A.log' scn min 123456 scn max 123456;

#转储日志文件头部信息
alter session set events 'immediate trace name redohdr level 10';

#转储整个日志文件
alter system dump logfile '/extend/oradata/hisdb/redo01A.log'

#查看转储文件路径
select value from v$diag_info where name='Default Trace File';

第1章 重做日志(Redo Log)

第2章 控制文件(Control File)

第3章 补充日志(Supplemental Logging)

第4章 恢复管理器(RMAN)

第5章 恢复编录(Recovery Catalog)

第6章 数据泵(Data Pump)

第7章 参数文件的备份与还原

第8章 控制文件的备份与恢复

第9章 关键数据文件备份与恢复

第10章 普通数据文件备份与恢复

第11章 只读数据文件备份与恢复

第12章 不完全数据库恢复

第13章 无备份情况下的恢复

第14章 闪回技术(Flashback)

第15章 恢复受损的数据块