Oracle-无备份情况下,如何手动恢复控制文件

1.测试场景

本文主要模拟在控制文件没有备份的情况下丢失,如何根据已有的参数文件、数据文件、在线日志信息去手动生成控制文件。

2.测试环境

Oracle单实例:11.2.0.4

数据文件目录:/u01/app/oracle/oradata/HJDB/datafile

在线日志目录:/u01/app/oracle/oradata/HJDB/onlinelog

3.创建文件所需要的信息和选项

以下这些选项跟数据库的参数文件、数据文件、在线日志没有强关联性,可以自行根据环境需要进行设置。

  1. reuse选项

    指定是否覆盖已有的控制文件。不指定,如果目录下有相同的控制文件,会创建失败报错,指定即直接覆盖。

    ORA-00200: control file could not be created
    ORA-00202: control file:
    '/u01/app/oracle/oradata/HJDB/controlfile/o1_mf_lyhr3fcp_.ctl'
    ORA-27038: created file already exists
    
  2. NORESETLOGS选项

    如果数据库是完整的恢复,包含完整的在线日志,可以选择NORESETLOGS方式创建。

    如果数据库是不完整的恢复,需要选择RESETLOGS方式创建。

  3. FORCE LOGGING选项

    数据库是否开启force logging 。

  4. ARCHIVELOG/NOARCHIVELOG选项

    数据库归档模式。

  5. MAXLOGFILES选项

    设置创建的控制文件的日志组数量,要大于当前的在线日志组group的大小,比如日志组有3组,分别为11,12,13,则MAXLOGFILES设置要大于13。

  6. MAXLOGMEMBERS选项

    设置创建的控制文件每个日志组的成员最大数量,通常为1-2。

  7. MAXDATAFILES选项

    设置创建的控制文件的最大数据文件数量,大于当前的数据文件数量,不超过db_files即可。

  8. MAXINSTANCES选项

    设置可以同时挂载和打开数据库的最大实例数。

  9. MAXLOGHISTORY选项

    设置控制文件记录的归档日志参考数量。

    这里我们按以下配置进行设置,数据库名DB_NAME暂时不填写。

    CREATE CONTROLFILE REUSE DATABASE "XXXX" NORESETLOGS FORCE LOGGING ARCHIVELOG
        MAXLOGFILES 20
        MAXLOGMEMBERS 2
        MAXDATAFILES 200
        MAXINSTANCES 2
        MAXLOGHISTORY 1024
    

4.获取相关信息

4.1.DB_NAME信息获取

4.1.1.alert日志的启动信息获取

$ cat alert_hjdb.log |grep -i DB_NAME
  db_name                  = "hjdb"
  db_name                  = "hjdb"
  db_name                  = "hjdb"

4.1.2.spfile/pfile文件的参数设置信息获取

$ cat /tmp/inithjdb.ora |grep -i db_name
*.db_name='hjdb'
$ strings spfilehjdb |grep -i db_name
*.db_name='hjdb'

4.1.3.bbed从数据文件头获取

位置block 1 offset 32-39

注意:这里在配置bbed读取文件时,需要知道数据文件的大小和file#,数据文件大小可以通过dbfsize进行获取确认,而file#可以通过操作系统dd+hexdump方式读取block 1 offset 52获取file#。

BBED> set file 1 block 1
  FILE#            1
  BLOCK#           1

BBED> p kcvfhhdr.kccfhdbn
text kccfhdbn[0]                            @32      H
text kccfhdbn[1]                            @33      J
text kccfhdbn[2]                            @34      D
text kccfhdbn[3]                            @35      B
text kccfhdbn[4]                            @36       
text kccfhdbn[5]                            @37       
text kccfhdbn[6]                            @38       
text kccfhdbn[7]                            @39

4.1.4.dd+strings也可以获取

# 通过dd转储block 1
$ dd if=/tmp/SYSTEM.355.1164882483 of=/tmp/db_name_tbs skip=1 count=1 bs=8192
# 通过strings命令获取字符串DB_NAME
$ strings /tmp/db_name_tbs 
J-:B"hjdb"--dbname

4.2.在线日志信息获取

4.2.1.获取日志大小

4.2.1.1.操作系统查看

通过操作系统层查看日志文件大小进行计算,需要减去block 0,再计算大小,因为block 0预留给操作系统记录OS信息的块。

$ ls -lrt
total 1536016
-rw-r----- 1 oracle oinstall 524288512 Apr 12 10:34 o1_mf_13_lyhrzrws_.log
-rw-r----- 1 oracle oinstall 524288512 Apr 12 10:34 o1_mf_11_lyhrzh7c_.log
-rw-r----- 1 oracle oinstall 524288512 Apr 12 10:35 o1_mf_12_lyhrzn7p_.log
$ echo $(((524288512-512)/1024/1024)),通过操作系统层查看的大小计算为500M
4.2.1.2.dbfsize查看
$ dbfsize o1_mf_12_lyhrzn7p_.log
Database file: o1_mf_12_lyhrzn7p_.log
Database file type: file system
Database file size: 1024000 512 byte blocks

4.2.2.获取日志组号

4.2.2.1.redo文件头获取
#通过dd命令转储block 1
$ dd if=o1_mf_12_lyhrzn7p_.log of=/tmp/redo12.log skip=1 count=1 bs=512
#通过hexdump以16进制的方式从offset 48位打开查看
$ hexdump -s 48 -n 2 /tmp/redo12.log
0000030 000c --->group:12
4.2.2.2.文件名推测
o1_mf_11_lyhrzh7c_.log--->group 11
o1_mf_12_lyhrzn7p_.log--->group 12
o1_mf_13_lyhrzrws_.log--->group 13
4.2.2.3.控制文件报错

通过create controlfile命令报错日志提示,进行校正获取group信息。

ERROR at line 1:
ORA-01503: CREATE CONTROLFILE failed
ORA-01224: group number in header 11 does not match GROUP 1
ORA-01517: log member:
'/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_11_lyhrzh7c_.log'

通过以上方式,获取到日志文件分别对应11、12、13,日志大小为500M,blocksize为512。

LOGFILE
  GROUP 11 '/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_11_lyhrzh7c_.log'  SIZE 500M BLOCKSIZE 512,
  GROUP 12 '/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_12_lyhrzn7p_.log'  SIZE 500M BLOCKSIZE 512,
  GROUP 13 '/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_13_lyhrzrws_.log'  SIZE 500M BLOCKSIZE 512

4.3.数据文件信息获取

4.3.1.数据文件数量

当前在数据文件目录下发现有11个数据文件。

$ ls -lrth
total 2.1G
-rw-r----- 1 oracle oinstall 5.1M Apr 17 15:00 o1_mf_users_m1k9dc1p_.dbf
-rw-r----- 1 oracle oinstall 546M Apr 17 15:00 o1_mf_undotbs1_m1k9dbyn_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test_m1k9d9vc_.dbf
-rw-r----- 1 oracle oinstall 921M Apr 17 15:00 o1_mf_system_m1k9dbyl_.dbf
-rw-r----- 1 oracle oinstall 531M Apr 17 15:00 o1_mf_sysaux_m1k9dbyp_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test_m1k9dc0t_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test_m1k9dbz0_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test_m1k9dbyy_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test_m1k9dbyw_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test5_m1k9dc18_.dbf
-rw-r----- 1 oracle oinstall  11M Apr 17 15:00 o1_mf_test1_m1k9dbyq_.dbf

4.3.2.file文件号和表空间号

通过file$基表获取file文件号和表空间号信息,存放在system file 1 block 233。

# 通过bbed打开system file 1 block 233
# 可以看到kdbr结构有12行数据,代表最多使用过12个数据文件
BBED> p kdbr
sb2 kdbr[0]                                 @86       8080
sb2 kdbr[1]                                 @88       7971
sb2 kdbr[2]                                 @90       7520
sb2 kdbr[3]                                 @92       7753
sb2 kdbr[4]                                 @94       7404
sb2 kdbr[5]                                 @96       7305
sb2 kdbr[6]                                 @98       7206
sb2 kdbr[7]                                 @100      7107
sb2 kdbr[8]                                 @102      7008
sb2 kdbr[9]                                 @104      6341
sb2 kdbr[10]                                @106      6810
sb2 kdbr[11]                                @108      6487

#查看第一行数据kdbr[0]的offset
BBED> p *kdbr[0]
rowdata[1043]
-------------
ub1 rowdata[1043]                           @8148     0x2c

BBED> 
#查看里面的数据,col 0为file 1,col 1为status status 为2表示启用,为1表示没有使用,col 2 为数据文件块,col 3为表空间号,为null表示没有使用
BBED> x /rnn offset 8148
rowdata[1043]                               @8148    
-------------
flag@8148: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8149: 0x00
cols@8150:   11

col    0[2] @8151: 1 
col    1[2] @8154: 2 
col    2[3] @8157: 64000 
col    3[1] @8161: 0 
col    4[2] @8163: 1 
col    5[5] @8166: 4194302 
col    6[3] @8172: 1280 
col    7[1] @8176: 0 
col    8[2] @8178: 7 
col    9[0] @8181: *NULL*
col   10[5] @8182: 4194306 
# 由于当前只有11个数据文件,所以需要检查每一行数据,确认是否存在数据文件缺失,还是file$里面记录的是曾经使用过的数据文件,这里我们看到file#10的status为1,并且表空间号为null,代表数据文件已经被删除,只有11个数据文件在使用。
BBED> x /rn offset 6409
rowdata[0]                                  @6409    
----------
flag@6409: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@6410: 0x01
cols@6411:   11

col    0[2] @6412: 10 
col    1[2] @6415: 1 
col    2[3] @6418: 1280 
col    3[0] @6422: *NULL*
col    4[0] @6423: *NULL*
col    5[1] @6424: 0 
col    6[1] @6426: 0 
col    7[1] @6428: 0 
col    8[5] @6430: 3066083 
col    9[0] @6436: *NULL*
col   10[5] @6437: 41943042 

然后再使用bbed打开每个数据文件头block 1的kccfhfno(offset 52)文件号,kcvfhtsn(offset 332)表空间号与file$里面记录的文件信息进行一一对应,确保数据文件数量一致。

BBED> p kcvfh.kcvfhhdr.kccfhfno
ub2 kccfhfno                                @52       0x0001

BBED> p kcvfh.kcvfhtsn
sword kcvfhtsn                              @332      0

确认完之后,我们就可以列出控制文件需要的数据文件信息。

DATAFILE
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_undotbs1_m1k9dbyn_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_system_m1k9dbyl_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_sysaux_m1k9dbyp_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_users_m1k9dc1p_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dbyy_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dbyw_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9d9vc_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test1_m1k9dbyq_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dc0t_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dbz0_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test5_m1k9dc18_.dbf'

4.4.数据库的字符集获取

character存储在基表props$下面,Oracle11g 在system file 1 block 801,Oracle19c 在system file 1 block 1321。

通过bbed读取system file 1 block 801获取。

BBED> set file 1 block 801
        FILE#           1
        BLOCK#          801

BBED> set count 8196
        COUNT           8196

BBED> set offset 7100
        OFFSET          7100

BBED> dump /v
 File: /u01/app/oracle/oradata/HJDB/datafile/o1_mf_system_m1k9dbyl_.dbf (1)
 Block: 801     Offsets: 7100 to 8191  Dba:0x00400321
-------------------------------------------------------
 69737469 63206465 66696e69 74696f6e l istic definition
 2c000311 4e4c535f 44415445 5f4c414e l ,...NLS_DATE_LAN
 47554147 4508414d 45524943 414e0d44 l GUAGE.AMERICAN.D
 61746520 6c616e67 75616765 2c00030f l ate language,...
 4e4c535f 44415445 5f464f52 4d415409 l NLS_DATE_FORMAT.
 44442d4d 4f4e2d52 520b4461 74652066 l DD-MON-RR.Date f
 6f726d61 742c0003 0c4e4c53 5f43414c l ormat,...NLS_CAL
 454e4441 52094752 45474f52 49414e0f l ENDAR.GREGORIAN.
 43616c65 6e646172 20737973 74656d2c l Calendar system,
 0103104e 4c535f43 48415241 43544552 l ...NLS_CHARACTER
 53455408 414c3332 55544638 0d436861 l SET.AL32UTF8.Cha  ---字符集
 72616374 65722073 65742c00 03164e4c l racter set,...NL
 535f4e55 4d455249 435f4348 41524143 l S_NUMERIC_CHARAC

通过dd+strings方式获取。

$ dd if=/tmp/SYSTEM.292.1151425093  of=/tmp/system_char skip=801 count=1 bs=8192
$ strings system_char 

NLS_DATE_LANGUAGE
AMERICAN
Date language,
NLS_DATE_FORMAT  DD-MON-RR
Date format,
NLS_CALENDAR  GREGORIAN
Calendar system,
NLS_CHARACTERSET
AL32UTF8
Character set,
NLS_NUMERIC_CHARACTERS
Numeric characters,
NLS_ISO_CURRENCY
AMERICA
ISO currency,
NLS_CURRENCY

5.创建控制文件

通过以上准备,我们获取到了手动恢复创建控制文件的基本信息。

CREATE CONTROLFILE REUSE DATABASE "HJDB" NORESETLOGS  ARCHIVELOG
    MAXLOGFILES 13
    MAXLOGMEMBERS 3
    MAXDATAFILES 20
    MAXINSTANCES 3
    MAXLOGHISTORY 1024
LOGFILE
  GROUP 11 '/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_11_lyhrzh7c_.log'  SIZE 500M BLOCKSIZE 512,
  GROUP 12 '/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_12_lyhrzn7p_.log'  SIZE 500M BLOCKSIZE 512,
  GROUP 13 '/u01/app/oracle/oradata/HJDB/onlinelog/o1_mf_13_lyhrzrws_.log'  SIZE 500M BLOCKSIZE 512
-- STANDBY LOGFILE
DATAFILE
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_undotbs1_m1k9dbyn_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_system_m1k9dbyl_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_sysaux_m1k9dbyp_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_users_m1k9dc1p_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dbyy_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dbyw_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9d9vc_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test1_m1k9dbyq_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dc0t_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test_m1k9dbz0_.dbf',
'/u01/app/oracle/oradata/HJDB/datafile/o1_mf_test5_m1k9dc18_.dbf'
CHARACTER SET AL32UTF8;

6.打开数据库

1 将数据库启动到nomount。

2 执行控制文件创建语句。

3 recover DATABASE恢复数据库。

4 alter database open打开数据库。

此文觉得很好,为了防止丢失,特记录下来。原文:公众号-勇敢牛牛的笔记-Oracle-无备份情况下,如何手动恢复控制文件

posted @ 2024-04-27 22:28  monkey6  阅读(142)  评论(0编辑  收藏  举报