1.測試場景
本文主要模擬在控制檔案沒有備份的情況下丟失,如何根據已有的引數檔案、資料檔案、線上日誌資訊去手動生成控制檔案。
2.測試環境
Oracle單例項:11.2.0.4
資料檔案目錄:/u01/app/oracle/oradata/HJDB/datafile
線上日誌目錄:/u01/app/oracle/oradata/HJDB/onlinelog
3.建立檔案所需要的資訊和選項
以下這些選項跟資料庫的引數檔案、資料檔案、線上日誌沒有強關聯性,可以自行根據環境需要進行設定。
-
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
-
NORESETLOGS選項
如果資料庫是完整的恢復,包含完整的線上日誌,可以選擇NORESETLOGS方式建立。
如果資料庫是不完整的恢復,需要選擇RESETLOGS方式建立。
-
ORCE LOGGING選項
資料庫是否開啟force logging 。
-
ARCHIVELOG/NOARCHIVELOG選項
資料庫歸檔模式。
-
MAXLOGFILES選項
設定建立的控制檔案的日誌組數量,要大於當前的線上日誌組group的大小,比如日誌組有3組,分別為11,12,13,則MAXLOGFILES設定要大於13。
-
MAXLOGMEMBERS選項
設定建立的控制檔案每個日誌組的成員最大數量,通常為1-2。
-
MAXDATAFILES選項
設定建立的控制檔案的最大資料檔案數量,大於當前的資料檔案數量,不超過db_files即可。
-
MAXINSTANCES選項
設定可以同時掛載和開啟資料庫的最大例項數。
-
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-無備份情況下,如何手動恢復控制檔案