經典故障:四個雷,3*2*2*3種隨機方法的特殊恢復案例
導讀:恢復專家前輩給我們精心準備了個故障,埋了四個雷,整個恢復過程感覺像是雲霄飛車,整理分享至此,希望對大家有幫助。
就給一個壓縮的system,起庫。
恢復過程
首先,獲取system檔案的字符集,資料庫名,然後建立引數檔案,重建控制檔案,這裡就不過多介紹,話不多說,先嚐試啟動資料庫。
第一個雷
SQL> startup nomount pfile='/gauss/init.ora';
ORACLE instance started.
Total System Global Area 396668928 bytes
Fixed Size 2253624 bytes
Variable Size 125832392 bytes
Database Buffers 264241152 bytes
Redo Buffers 4341760 bytes
SQL> @cf
Control file created.
ORA-00279: change 4936537 generated at 04/21/2020 00:03:57 needed for thread 1
ORA-00289: suggestion :
/guass/app/oracle/product/11.2.0/db_1/dbs/arch1_41_1033397865.dbf
ORA-00280: change 4936537 for thread 1 is in sequence #41
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
cancel
Media recovery cancelled.
SQL> alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-00704: bootstrap process failure
ORA-00604: error occurred at recursive SQL level 1
ORA-01578: ORACLE data block corrupted (file # 1, block # 338)--壞塊
ORA-01110: data file 1: '/gauss/system.dbf'
Process ID: 32245
Session ID: 1 Serial number: 3
資料啟動報file 1, block 338存在壞塊的錯誤,我們來查一下這個塊對應的物件。
TABLESPACE_NAME SEGMENT_TYPE OWNER SEGMENT_NAME
------------------ --------------- ------------- --------------
SYSTEM INDEX SYS I_OBJ1
這個物件是I_OBJ1,I_OBJ1是什麼?
SQL> select * from bootstrap$ where SQL_TEXT like '%I_OBJ1%' order by LINE#;
LINE# OBJ# SQL_TEXT
---------- ---------- --------------------------------------------------------------------------------
36 36 CREATE UNIQUE INDEX I_OBJ1 ON OBJ$(OBJ#,OWNER#,TYPE#) PCTFREE 10 INITRANS 2 MAXT
RANS 255 STORAGE ( INITIAL 64K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PC
TINCREASE 0 OBJNO 36 EXTENTS (FILE 1 BLOCK 336))
I_OBJ1是核心基表OBJ$的一個索引,當普通的索引出現壞塊,我們可以透過重建去處理,但是OBJ#<59 的索引出現壞塊,是不能夠透過rebuild的方式處理。資料庫open的情況下可以透過swap的方式處理,不過這裡我們資料庫都沒開啟。
首先我們先來介紹下資料庫啟動的過程:
1、在system 表空間的第一個資料檔案的特定偏移位置,找到root dba變數
2、root dba變數的值就是指向sys.bootstrap$表的物理位置的指標
3、sys.bootstrap$表中記錄了資料庫基礎字典表的物理位置
4、基礎字典表內記錄了使用者段段頭的物理儲存位置
下一步就是要透過某個段的segment header block從資料檔案中直接讀出表的資料。
在sys.bootstrap$表中記錄的資料字典表的create語句,還有一部分是沒有直接指定儲存位置的,比如簇成員。
那麼怎麼去爬過第一個雷?這裡有兩個方案:
最簡單的方法就是透過bbed cp同平臺同版本的相同塊去覆蓋。
BBED> copy file 6 block 338 to file 1 block 338
但是如果I_OBJ1存在大量的壞塊情況下,cp的效率比較低。
方法二
刪除I_OBJ1,但是我們這裡不是刪除IND$裡的I_OBJ1索引,再次重啟的時候又建立了,這裡我們需要刪除sys.bootstrap裡的索引。
BBED> x /rnnc *kdbr[1]
rowdata[3681] @7322
-------------
flag@7322: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@7323: 0x01
cols@7324: 3
col 0[2] @7325: 36
col 1[2] @7328: 36
col 2[208] @7331: CREATE UNIQUE INDEX I_OBJ1 ON OBJ$(OBJ#,OWNER#,TYPE#) P
CTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1024K MINEXTE
NTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 OBJNO 36 EXTENTS (FILE 1 BLOCK 33
6))
BBED> assign /x offset 7322 =0x3c --刪除索引
ub1 rowdata[0] @7322 0x3c
BBED> x /rnnc dba 1,523 *kdbr[1]
rowdata[3681] @7322
-------------
flag@7322: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
lock@7323: 0x01
cols@7324: 0 --已經刪除
BBED> sum apply
Check value for File 1, Block 523:
current = 0x7e06, required = 0x7e06
方法三
[ora11@zdata bin]$ strings $ORACLE_HOME/bin/oracle |wc -l1341571
11.2.0.4的執行檔案包含1341571個函式,可以透過修改oracle執行檔案指定<hint +full>,繞過索引I_OBJ1來處理。
第二個雷
透過上面兩種方式排了第一個雷,我們順利到達第二關。趕緊嘗試開啟,看看又會報什麼錯。
SQL> oradebug event 10046 trace name context forever,level 12;
Statement processed.
SQL> alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-00704: bootstrap process failure
ORA-00604: error occurred at recursive SQL level 1
ORA-01555: snapshot too old: rollback segment number 27 with name
"$" too small
Process ID: 17397
Session ID: 1 Serial number: 5
當oracle讀取一個塊,是否需要undo來完成一致性讀,有很多種情況:
1. itl有活動事務,回查undo段頭發現事務確實是活動狀態,那麼肯定要undo來做一致性讀
2. itl有活動事務,回查undo段頭發現事務已經提交或者回滾,那麼需要做塊清除來確定commit scn,如果query scn<commit scn,則也需要undo來做一致性讀塊清除一直要找到大於query scn的commit scn,upper的也可以,才會做一致性讀 否則直接01555了
3. itl事務已經提交 flag為C/U/CU,則掃描itl的commit scn,如果發現有query scn<commit scn,則也需要undo來做一致性讀
WAIT #140193663907536: nam='db file sequential read' ela= 788 file#=1 block#=241 blocks=1 obj#=18 tim=1587333670688800
=====================
PARSING IN CURSOR #140193661586512 len=142 dep=2 uid=0 oct=3 lid=0 tim=1587333670689091 hv=361892850 ad='775596a0' sqlid='7bd391hat42zk'
select /*+ rule */ name,file#,block#,status$,user#,undosqn,xactsqn,scnbas,scnwrp,DECODE(inst#,0,NULL,inst#),ts#,spare1 from undo$ where us#=:1
END OF STMT
PARSE #140193661586512:c=242,e=243,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=3,plh=0,tim=1587333670689090
BINDS #140193661586512:
BBED> p ktbbh
.........省略
ub2 kxidusn @44 0x001b
ub2 kxidslt @46 0x000b
ub4 kxidsqn @48 0x00000186
struct ktbituba, 8 bytes @52
ub4 kubadba @52 0x00c00a97
ub2 kubaseq @56 0x0219
ub1 kubarec @58 0x26
ub2 ktbitflg @60 0x2001 (KTBFUPB)
union _ktbitun, 2 bytes @62
sb2 _ktbitfsc @62 0
ub2 _ktbitwrp @62 0x0000
ub4 ktbitbas @64 0xffffffff --這裡被改成0xffffffff
這裡低位scn都改成最大值了,難怪怎麼poke scn都沒效果。。這個雷特麼陰險,太壞了。
好了我們知道問題所在了,就是ktbitbas被人工改成0xffffffff,那麼恢復方案也有兩種。
方法一
修改scn,我們手動修改ktbitbas的值。
BBED> assign ktbbhitl[0].ktbitbas=0x004b531fub4 ktbitbas @64 0x004b531f
方法二
既然低位已經最大了,再怎麼推也不會超過0xffffffff,那麼我們就嘗試poke推進高位scn。
SQL> oradebug setmypid
SQL> oradebug dumpvar sga kcsgscn_
kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000
SQL> oradebug poke 0x06001AE74 4 0x50
BEFORE: [06001AE70, 06001AE78) = 00000000 00000000
AFTER: [06001AE70, 06001AE78) = 004B60E0 00000000
第三個雷
SQL> alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-01173: data dictionary indicates missing data file from system tablespace
Process ID: 26639
Session ID: 1 Serial number: 3
看到這個報錯,說明順利進入第三關。
方法一
透過一鍵指令碼設定*._corrupted_rollback_segments隱患引數,遮蔽回滾段。
*._corrupted_rollback_segments='_SYSSMU28_79026890$','_SYSSMU24_100127047$','_SYSSMU28_79026890$','_SYSSMU21_1449495591$','_SYSSMU24_100127047$','_SYSSMU21_1449495591$','_SYSSMU30_493042799$','_SYSSMU30_493042799$','_SYSSMU23_1725104698$','_SYSSMU23_1725104698$','_SYSSMU22_3628056578$','_SYSSMU22_3628056578$','_SYSSMU25_3360715651$','_SYSSMU22_3628056578$','_SYSSMU25_3360715651$','_SYSSMU22_36280565.......
方法二
SQL> select OWNER,SEGMENT_NAME,FILE_ID,BLOCK_ID from dba_extents where segment_name='UNDO$';
OWNER SEGMENT_NAME FILE_ID BLOCK_ID
---------- --------------- ---------- ----------
SYS UNDO$ 1 224
BBED> p ktetb
struct ktetb[0], 8 bytes @108
ub4 ktetbdba @108 0x004000e1--extent的首地址
ub4 ktetbnbk @112 0x00000007--連續7個塊
BBED> x /rnc *kdbr[0
rowdata[2337] @8146
-------------
flag@8146: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8147: 0x00
cols@8148: 17
col 0[1] @8149: 0
col 1[6] @8151: SYSTEM
col 2[1] @8158: .
col 3[2] @8160: ..
......省略
BBED> x /rnc *kdbr[1
rowdata[2267] @8076
-------------
flag@8076: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8077: 0x00
cols@8078: 17
col 0[2] @8079: 1
col 1[19] @8082: _SYSSMU1_770609302$ --需要刪除
col 2[2] @8102: ..
col 3[2] @8105: ..
col 4[3] @8108: ...
......省略
1、在資料字典中存放資料段(對應表或分割槽)頭的物理位置
2、在資料段頭存放段中所有extent(即連續的block集合)的物理位置
ktetb其實就是UNDO$的extent map,該結構體記錄了segment中的extent的首地址。
透過一鍵指令碼找到dba 0x004000e1,也就是1,225,然後連續7個塊,刪除裡面除了system的其他所有回滾段,這種方法實際操作太麻煩,大家有興趣可以挑戰下。
第四個雷
SQL> alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 26280
Session ID: 1 Serial number: 3
SQL> oradebug event 10046 trace name context forever,level 12;
SQL> alter database open resetlogs;
alter database open resetlogs
--後臺alert的報錯
SMON: enabling cache recovery
Exception [type: SIGSEGV, Address not mapped to object] [ADDR:0xD0C5CD7] [PC:0x97DF62E, kgebse()+776] [flags: 0x2, count: 2]
Fri Apr 24 06:42:13 2020
PMON (ospid: 19501): terminating the instance due to error 397
--file#=1 block#=140需要關注
WAIT #140452738872120: nam='db file sequential read' ela= 670 file#=1 block#=140 blocks=1 obj#=0 tim=1587681730297305
Exception [type: SIGSEGV, Address not mapped to object] [ADDR:0xD0C5CD7] [PC:0x97E0BBA, kgegpa()+40] [flags: 0x0, count: 1]
DDE previous invocation failed before phase II
DDE was called in a 'No Invocation Mode'
----- Start Diag Diagnostic Dump -----
Diag diagnostic dump is performed due to an error in the diagfw code during error handling.
DDE is switched to protected mode during the diagnostic dump to prevent recursive errors in the error hadnling code.
TABLESPACE_NAME SEGMENT_TYPE OWNER SEGMENT_NAME-------------------- ------------------ ---------- ---------------SYSTEM ROLLBACK SYS SYSTEM
BBED> p dba 1,140 ktubh
struct ktubh, 22 bytes @20
struct ktubhxid, 8 bytes @20
ub2 kxidusn @20 0x0000
ub2 kxidslt @22 0x003b
ub4 kxidsqn @24 0x0000002b
ub2 ktubhseq @28 0x0025 --seq 是0x0025
ub1 ktubhcnt @30 0x03
ub1 ktubhirb @31 0x03
ub1 ktubhicl @32 0x00
ub1 ktubhflg @33 0x00
BBED> p dba 1,128 ktuxc
struct ktuxc, 104 bytes @4148
struct ktuxcscn, 8 bytes @4148
ub4 kscnbas @4148 0x004996f7
ub2 kscnwrp @4152 0x0000
.....省略
struct ktuxcfbp[0], 12 bytes @4192
struct ktufbuba, 8 bytes @4192
ub4 kubadba @4192 0x0040008c
ub2 kubaseq @4196 0x0030 --seq 是0x0030
ub1 kubarec @4198 0x03
sb2 ktufbext @4200 1
sb2 ktufbspc @4202 7340
這裡感覺是人為把128塊的offset 4196由0x0025改成了0x0030
把128塊的offset 4196從0x0030改成了0x0025
assign dba 1,128 4196=0x0025
ub2 kubaseq @4196 0x0025
方法二
需要修改ktuxcnfb和ktuxcfbp[1] 即可。其中將ktuxcnfb修改為0,ktuxcfbp[1]中的uba修改為0,表示回滾的時候讓oracle認為沒有可以分配的undo塊,相當於不回滾。
modify /x 00 offset 4168
BBED> modify /x 000000 offset 4192
方法三
透過strace跟蹤,得到如下的trace。
01:13:27 write(14, "[32]: ktuiup []", 15) = 15 <0.000012> --ktuiup
01:13:27 write(15, "!gF\n", 4) = 4 <0.000011>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425947 <0.000009>
01:13:27 write(14, "\n", 1) = 1 <0.000011>
01:13:27 write(15, "!A1\n", 4) = 4 <0.000012>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425948 <0.000010>
01:13:27 write(14, "[33]: ktuini []", 15) = 15 <0.000012> ------注意這裡ktuini函式
01:13:27 write(15, "!gF\n", 4) = 4 <0.000011>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425963 <0.000009>
01:13:27 write(14, "\n", 1) = 1 <0.000012>
01:13:27 write(15, "!A1\n", 4) = 4 <0.000012>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425964 <0.000010>
01:13:27 write(14, "[34]: adbdrv []", 15) = 15 <0.000011>
01:13:27 write(15, "!gF\n", 4) = 4 <0.000012>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425979 <0.000009>
01:13:27 write(14, "\n", 1) = 1 <0.000012>
01:13:27 write(15, "!A1\n", 4) = 4 <0.000011>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425980 <0.000009>
01:13:27 write(14, "[35]: opiexe []", 15) = 15 <0.000012>
01:13:27 write(15, "!gF\n", 4) = 4 <0.000011>
01:13:27 lseek(14, 0, SEEK_CUR) = 3425995 <0.000009>
01:13:27 write(14, "\n", 1) = 1 <0.000012>
既然資料庫呼叫函式ktuini報錯,那我們就透過再這個函式設定斷點,然後匯出資料。
--session 1
(gdb) break ktuini
Breakpoint 1 at 0xf21352
(gdb) c
Continuing.
--session 2
匯出資料
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
exp \'/ as sysdba \' file=/home/ora11/meta.dmp ROWS=n buffer=102400000
總結
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31556440/viewspace-2701008/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- qcow2恢復案例
- ORACLE備份&恢復案例(3)Oracle
- ORACLE備份&恢復案例(2)Oracle
- 經典IT原版進口圖書 2-3 折
- Python3+pygame實現Windows經典掃雷PythonGAMWindows
- oracle10gR2之RMAN異機恢復案例Oracle
- 資料恢復經典案例分析-raid兩塊硬碟離線恢復資料恢復AI硬碟
- 經典遊戲《掃雷》的隱祕角落,蘊含著生活的3個“終極真相”遊戲
- oracle drop table purge無備份bbed恢復(2/3)Oracle
- mysql 從 frm 檔案恢復 table 表結構的3種方法MySql
- Windows XP 系統故障恢復寶典(轉)Windows
- 特殊的恢復操作
- 經典SQL-2SQL
- NTFS格式大硬碟資料恢復特殊案例分析(轉)硬碟資料恢復
- 手機檔案轉存隨身碟,2種實用方法任你選擇,3分鐘學會不再求人教
- 控制檔案的恢復方法(四)
- PHP實現四捨五入的3種方法PHP
- 爬蟲案例2-爬取影片的三種方式之一:DrissionPage篇(3)爬蟲
- oracle11gR2_64之rman異機恢復(FS->FS)完整案例Oracle
- DB2恢復DB2
- 經典SQL面試題2SQL面試題
- 經典掃雷遊戲Web版遊戲Web
- 解析ESX SERVER故障資料恢復方法Server資料恢復
- 恢復誤刪linux -ext3-ext2 檔案系統檔案的操作方法-轉載Linux
- 【儲存資料恢復】EqualLogic PS系列儲存磁碟故障的資料恢復案例資料恢復
- Web3與Web2的同步機制經驗總結Web
- 思科路由器密碼恢復的經典方案路由器密碼
- MongoDB副本集故障恢復機制概述MongoDB
- 恢復案例:熱備期間例項故障解決
- 【伺服器資料恢復】Vsan節點虛擬機器磁碟元件出現故障的資料恢復案例伺服器資料恢復虛擬機元件
- 【伺服器資料恢復】VSAN故障導致虛擬機器無法訪問的資料恢復案例伺服器資料恢復虛擬機
- 伺服器資料恢復-2盤raid0陣列資料恢復案例伺服器資料恢復AI陣列
- EOCR_3DM2-WRDUWZ/3DM2-WRDBWZ/3DM2-WRDBHZ3D
- 成功案例分享-伺服器3塊硬碟離線恢復成功伺服器硬碟
- db2 恢復drop後的表的一個操作DB2
- db2經典實驗內容,希望大家趕快動手!(第3部)DB2
- InfoGAN:一種無監督生成方法 | 經典論文復現
- springboot3+vue3(四.2)ThreadLocal最佳化Spring BootVuethread