oracle資料庫特種恢復技術(五)--redo篇

jinqibingl發表於2012-10-04

oracle資料庫特種恢復技術(五)--redo篇  

oracle資料庫特種恢復技術(五)--redo篇
作者:謝浩


Oracle資料庫特種恢復技術(一)—原理篇連結:http://www.itpub.net/thread-1507760-1-1.html
oracle資料庫特種恢復技術(二)—塊內篇連結:http://www.itpub.net/thread-1507766-1-1.html
oracle資料庫特種恢復技術(三)—轉換篇連結:http://www.itpub.net/thread-1507774-1-1.html
Oracle資料庫特種恢復技術(四)—實驗篇連結:http://www.itpub.net/thread-1510202-1-1.html


      繼續上一篇的內容。
      本篇圍繞redo日誌挖掘展開,可以說是本系列中對資料庫恢復最無足輕重的一篇。之所以這樣說是因為,只有在資料庫及其備份出現嚴重故障的特殊情況下才會用到本系列所描述的技術,而這種情況下,少量的資料完整性缺失已經是無足輕重的問題了。但本篇所分析的內容對資料變更軌跡的挖掘、資料庫同步技術等都有很大意義。
1、對測試表分別進行insert和update操作,並分別記錄scn:
SELECTDbms_Flashback.get_system_change_number() from dual;
insert into xh_tempvalues('s11','s21','s31',1,2,'s4',sysdate,sysdate,sysdate,'s5','s','d','f');
commit;
SELECTDbms_Flashback.get_system_change_number() from dual;
SELECT Dbms_Flashback.get_system_change_number()from dual;
update xh_temp a set a.object_name='test1'where a.object_name = 's2';
commit;
SELECTDbms_Flashback.get_system_change_number() from dual;
2、以scn base方式分別dump兩個操作的線上redolog:
Alter system dump logfile '/u01/app/oracle/oradata/PHONEDB/onlinelog/o1_mf_3_6lf2hxow_.log'scn min 21184829 scn max 21184832;
alter system dump logfile'/u01/app/oracle/oradata/PHONEDB/onlinelog/o1_mf_3_6lf2hxow_.log' scn min21184178 scn max 21184181;
3、從dump的trace檔案中分別獲得兩個操作的redo記錄的rba,使用dd工具複製redolog檔案相應位置的二進位制程式碼:
ddif=/u01/app/oracle/oradata/PHONEDB/onlinelog/o1_mf_3_6lf2hxow_.logof=./update.dd count=10 skip=9269 bs=512
ddif=/u01/app/oracle/oradata/PHONEDB/onlinelog/o1_mf_3_6lf2hxow_.logof=./updateC2.dd count=10 skip=9971 bs=512

這裡的bs選擇512是根據oracle軟體redo的block尺寸,redo檔案的block size不同於資料檔案,而是與os單次io的塊大小像匹配的,在linux、aix、windows中預設一次io是512位元組,hp ux中預設是1024位元組。Linux系統可以透過fdisk命令檢視os blocksize。這個block size會在redolog的第一個塊的偏移20位置用4位元組儲存(來自Dissecting the Redo Logs)Oracle這樣設計的目的是為了儘量保證redo寫入的安全性,保證io異常時不會有“切塊”的情況發生,因為真正保證資料庫資料的並不是資料檔案,而是重做日誌。(但是如果物理儲存裝置帶有快取,還是不能避免會有部分資料丟失)

dd輸出:
00000000h: 01 22 00 00 F8 44 01 00 FB 02 0000 10 80 38 9F ; .
00000010h: 90 03 00 00 0D 05 00 00 35 60 4201 02 00 06 C5 ; ?......5`B....?
00000020h: 00 00 00 00 61 02 C1 02 00 00 0100 02 00 00 00 ; ....a.?........
00000030h: 02 00 00 00 00 63 61 74 34 60 4201 00 00 75 63 ; .....cat4`B...uc
00000040h: 72 70 01 80 02 C1 20 02 C1 1A 2C00 08 03 C2 4C ; r
00000050h: 46 9D D2 2D 0B 02 01 00 03 00 0000 E6 66 C0 00 ; F澮-........鎓?
00000060h: 0F 60 42 01 00 00 01 00 02 02 73C4 16 00 18 00 ; .`B.......s?...
00000070h: 31 00 13 00 07 00 02 00 00 00 0000 01 00 0D 00 ; 1...............
00000080h: 01 00 AB 0C 01 01 00 00 00 00 0000 05 00 28 00 ; ..?..........(.
00000090h: 29 33 00 00 93 0D 80 00 77 13 3100 E6 66 C0 00 ; )3.
000000a0h: E3 66 C0 00 FA 12 02 01 01 00 0000 2C 01 08 00 ; 鉬??......,...
000000b0h: 00 00 13 01 07 00 00 00 00 00 0000 00 00 00 00 ; ................
000000c0h: 00 00 00 00 36 00 64 00 00 18 0000 00 6C 6F 63 ; ....6.d......loc
000000d0h: 41 47 45 4E 54 5F 53 54 41 54 5553 5F 4D 41 52 ; AGENT_STATUS_MAR
000000e0h: 4B 45 52 28 78 6F 0C 01 16 14 0306 C1 04 1E 37 ; KER(xo......?.7
000000f0h: 59 61 02 C1 41 47 45 4E 54 53 5F4D 41 52 4B 45 ; Ya.罙GENTS_MARKE
00000100h: 44 6F 63 61 30 69 6F 6E 05 02 1900 02 00 FF FF ; Doca0ion......??
00000110h: 49 00 80 00 ED 5F 42 01 00 00 0000 02 00 FF FF ; I??
00000120h: 04 00 20 00 28 00 15 00 29 33 0000 93 0D 80 00 ; .. .(..
。。。。。。。。。。。。。。。。。。。。。省略。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
其中重要資訊如下:
前4個位元組為redo標識。

從offset 4起佔4位元組的是該redoblock的rba:F8 44 01 00。

從offset 12起佔1位元組是該redoblock中第一個redo record的偏移地址:10(一個位元組最多表示到255,因此如果一個redo block中被上一個redo block中的redo record佔用超過255位元組,則該redo block的剩餘空間將不再被使用)。


4、根據上一步驟得到的offset,找到第一個redorecord:90 03 00 00 0D 05 00 00 …………..,其中前4位元組90 03 00 00表示該redorecord的長度390,之後的0D是一個叫做VLD的變數,該變數直接決定著redo record header的長度,我一直沒有找到該變數和redo record header長度之間的對應關係,但是透過分析得出,最重要的增刪改操作(即op為11.*的操作)vld為0D,對應的redo record header長度為68位元組,事務相關操作(即op為5.*的操作)vld為05,對應的redo record header長度為68位元組。
5、由於該redo record中vld為0D,所以第一個改變向量的物理位置為redo record開始offset 68的位置:
00000054h: 0B 02 01 00 03 00 00 00 E6 66 C000 0F 60 42 01 ; ........鎓?.`B.
00000064h: 00 00 01 00 02 02 73 C4 16 00 1800 31 00 13 00 ; ......s?...1...
00000074h: 07 00 02 00 00 00 00 00 01 000D                ; ...........

改變向量中第1、2個位元組是該操作的opcode,0B 02轉換為10進製為11 2,表示單行插入操作。(op code程式碼詳細資訊後附)。

改變向量開始offset 24位置,記錄了該改變向量中的記錄長度列表:
0000006ch: 16 00 18 00 31 00 13 00 07 00 0200 00 00 00 00 ; ....1...........
0000007ch: 01 00 0D 00 01 00 AB 0C                         ; ......?
    該列表中,每個記錄的長度佔兩個位元組儲存,第一個長度是指列表本身的長度,列表中的存放的長度數值,指的是對應記錄的有效長度,在檔案中儲存的記錄的實際長度要在有效長度的基礎上向上增加到4的倍數,比如第1、2位元組:16 00轉換為10進製為22,所以該列表的長度就是24位元組,最後兩個位元組為填充位元組,沒有實際意義。
    將其中列表轉換為10進位制,並按4位元組補齊後為:
18 00 31 00 13 00 07 00 02 00 00 00 00 0001 00 0D 00 01 00
對應
24   52  20   8    4     0   0   4    16    4
長度列表之後就是記錄的實際值:
00000084h: 01 01 00 00 00 00 00 00 05 00 2800 29 33 00 00 ; ..........(.)3..
00000094h: 93 0D 80 00 77 13 31 00 E6 66 C000 E3 66 C0 00 ; ?
000000a4h: FA 12 02 01 01 00 00 00 2C 01 0800 00 00 13 01 ; ?......,.......
000000b4h: 07 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 ; ................
000000c4h: 36 00 64 00 00 18 00 00 00 6C 6F63 41 47 45 4E ; 6.d......locAGEN
000000d4h: 54 5F 53 54 41 54 55 53 5F 4D 4152 4B 45 52 28 ; T_STATUS_MARKER(
000000e4h: 78 6F 0C 01 16 14 03 06 C1 04 1E37 59 61 02 C1 ; xo......?.7Ya.?
000000f4h: 41 47 45 4E 54 53 5F 4D 41 52 4B45 44 6F 63 61 ; AGENTS_MARKEDoca
00000104h: 30 69 6F 6E                                     ; 0ion

這部分中,前24位元組對應dump檔案中的ktb結構體,offset 24開始的52位元組對應dump檔案中的kdo結構體,kdo結構體中一個重要的變數就是offset20位置的solt變數,該變數記錄了update操作對應的行號,該行號對應的是資料行在data block中的行號,也就是rowid中的行號,至此,已經在redolog中獲得了update操作所對應的物件id、dba、行號三個資訊,根據此三個資訊已經可以計算出redo record操作的行的rowid了。

繼續觀察,kdo結構體後緊隨的是操作的欄位編號,佔4個位元組:01 00 40 04,這裡由於前面資訊長度列表裡這段資訊的長度是1,所以有效資料是01,其後的00 40 04為填充位,無意義。再往後儲存的是具體操作的欄位的值74 65 73 74 31 00 01 00。
SQL> select dump('test1',1016) fromdual;
DUMP('TEST1',1016)
--------------------------------------------------
Typ=96 Len=5 CharacterSet=ZHS16GBK:74,65,73,74,31
可以看到,和dump函式的輸出相吻合,最後3個位元組的00 01 00,還是填充位,無意義。
      這就是一個update操作最關鍵的修改資料塊的改變向量的全部內容,此後在同一redo record中還有其他操作的改變向量,如op為5.1、5.2是對回滾段的相應修改,都屬於事務操作的範疇。
      Insert操作與update操作的區別是沒有“欄位編號”這一部分資訊(因為用不到),只有ktb、kdo、欄位值這三個部分。
      Delete操作則只有ktb、kdo兩個部分,直接按照kdo中的slot行號資訊,加之前的object號,dba就能定位到要刪除的行。
      至此,redolog中已經能夠解出對資料的操作,只要根據不同的op code就能還原redo sql,在這之後又遇到了一個問題,就是如何界定redo log中哪些記錄屬於一個事務。對此我做了如下實驗,在session a中做一個update操作不提交,然後在session b中再做一個update操作並提交,然後再返回session a中提交事務,這樣session a中的事務對應的redo 記錄就必然被session b中的事務所分割,這個目的是達到了,但是我始終沒有找到session a的redo記錄之間的聯絡,session a的事務的改變向量被分割到多個redo record中,沒有任何線索能將其串聯。為此,一度陷入僵局。

之後我轉換了一種思路:這一部分分析的目的,是在恢復資料之後保證資料的準確性,也就是說,要在人工模擬oracle開啟過程之後再模擬oracle的recovery database過程。那麼,套用oracle本身的行為模式是良好的選擇,即,先將redolog裡所有對應start scn之後的redo record全部應用前滾,然後再根據data block上的狀態flag進行回滾。也就是說oracle本身在redolog這個環節並不需要界定事務,事務的最終標識是在資料塊上的相關鎖的產生和清除來界定的。

至此redo部分已經可以進行簡單的應用,下一步是要根據資料塊上的事務標識,透過undo構造一致性塊,進一步增加恢復的精確性。
附op code列表(來自網路):
格式:layer: opcode
       LAYER的含義:
               4 — Block Cleanout
               5 — Transaction Management
             10 — 索引操作
             11 — 行操作
              13 — 段[url=]管理[/url]
              14 — Extent 管理
              17 — 表空間管理
              18 — Block Image (Hot Backups)
              19 — Direct Loader
              20 — Compatibility segment
              22 — 本地管理表空間
              23 — Block Writes
              24 — DDL語句
Layer 1 : Transaction Control - KCOCOTCT     
   Opcode 1 : KTZFMT
   Opcode 2 : KTZRDH
   Opcode 3 : KTZARC
   Opcode 4 : KTZREP
Layer 2 : Transaction Read -  KCOCOTRD     
Layer 3 : Transaction Update -  KCOCOTUP     
Layer 4 : Transaction Block -  KCOCOTBK     [ktbcts.h]
         Opcode 1 : Block Cleanout
         Opcode 2 : Physical Cleanout
         Opcode 3 : Single Array Change
         Opcode 4 : Multiple Changes to an Array
         Opcode 5 : Format Block
Layer 5 : Transaction Undo -  KCOCOTUN     [ktucts.h]
         Opcode 1 : Undo block or undo segment header - KTURDB
         Opcode 2 : Update rollback segment header - KTURDH
         Opcode 3 : Rollout a transaction begin
         Opcode 4 : Commit transaction (transaction table update)
- no undo record
         Opcode 5 : Create rollback segment (format) - no undo record
         Opcode 6 : Rollback record index in an undo block - KTUIRB
         Opcode 7 : Begin transaction (transaction table update)
         Opcode 8 : Mark transaction as dead
         Opcode 9 : Undo routine to rollback the extend of a rollback segment
         Opcode 10 :Redo to perform. the rollback of extend of rollback segment
                    to the segment header.
         Opcode 11 :Rollback DBA in transaction table entry - KTUBRB
         Opcode 12 :Change transaction state (in transaction table entry)
         Opcode 13 :Convert rollback segment format (V6 -> V7)
         Opcode 14 :Change extent allocation parameters in a rollback segment
         Opcode 15 :
         Opcode 16 :
         Opcode 17 :
         Opcode 18 :
         Opcode 19 : Transaction start audit log record
         Opcode 20 : Transaction continue audit log record     
         Opcode 24 : Kernel Transaction Undo Relog CHanGe - KTURLGU
Layer 6 : Control File -  KCOCODCF     [tbs.h]
Layer 10 : INDEX -  KCOCODIX     [kdi.h]
         Opcode 1 : load index block (Loader with direct mode)
         Opcode 2 : Insert leaf row
         Opcode 3 : Purge leaf row
         Opcode 4 : Mark leaf row deleted
         Opcode 5 : Restore leaf row (clear leaf delete flags)
         Opcode 6 : Lock index block
         Opcode 7 : Unlock index block
         Opcode 8 : Initialize new leaf block
         Opcode 9 : Apply Itl Redo
         Opcode 10 :Set leaf block next link
         Opcode 11 :Set leaf block previous link
         Opcode 12 :Init root block after split
         Opcode 13 :Make leaf block empty
         Opcode 14 :Restore block before image
         Opcode 15 :Branch block row insert
         Opcode 16 :Branch block row purge
         Opcode 17 :Initialize new branch block
         Opcode 18 :Update keydata in row
         Opcode 19 :Clear row’s split flag
         Opcode 20 :Set row’s split flag
         Opcode 21 :General undo above the cache (undo)
         Opcode 22 :Undo operation on leaf key above the cache (undo)
         Opcode 23 :Restore block to b-tree
         Opcode 24 :Shrink ITL (transaction entries)
         Opcode 25 :Format root block redo
         Opcode 26 :Undo of format root block (undo)
         Opcode 27 :Redo for undo of format root block
         Opcode 28 :Undo for migrating block
         Opcode 29 :Redo for migrating block
         Opcode 30 :IOT leaf block nonkey update
         Opcode 31 :Cirect load root redo
         Opcode 32 :Combine operation for insert and restore rows
Layer 11 : Row Access -  KCOCODRW     [kdocts.h]
         Opcode 1 : Interpret Undo Record (Undo)
         Opcode 2 : Insert Row Piece
         Opcode 3 : Drop Row Piece
         Opcode 4 : Lock Row Piece
         Opcode 5 : Update Row Piece
         Opcode 6 : Overwrite Row Piece
         Opcode 7 : Manipulate First Column (add or delete the 1rst column)
         Opcode 8 : Change Forwarding address
         Opcode 9 : Change the Cluster Key Index
         Opcode 10 :Set Key Links (change the forward & backward key links
                    on a cluster key)
         Opcode 11 :Quick Multi-Insert (ex: insert as select …)
         Opcode 12 :Quick Multi-Delete
         Opcode 13 :Toggle Block Header flags
Layer 12 : Cluster -  KCOCODCL     [?]
Layer 13 : Transaction Segment -  KCOCOTSG     [ktscts.h]
         Opcode 1 : Data segment format
         Opcode 2 : Merge
         Opcode 3 : Set link in block
         Opcode 4 : Not used
         Opcode 5 : New block (affects segment header)
         Opcode 6 : Format block (affects data block)
         Opcode 7 : Record link
         Opcode 8 : Undo free list (undo)
         Opcode 9 : Redo free list head (called as part of undo)
         Opcode 9 : Format free list block (freelist group)
         Opcode 11 :Format new blocks in free list
         Opcode 12 :free list clear
         Opcode 13 :free list restore (back) (undo of opcode 12)
Layer 14 : Transaction Extent -  KCOCOTEX     [kte.h]
         Opcode 1 : Add extent to segment
         Opcode 2 : Unlock Segment Header
         Opcode 3 : Extent DEaLlocation (DEL)
         Opcode 4 : Undo to Add extent operation (see opcode 1)
         Opcode 5 : Extent Incarnation number increment
         Opcode 6 : Lock segment Header
         Opcode 7 : Undo to rollback extent deallocation (see opcode 3)
         Opcode 8 : Apply Position Update (truncate)
         Opcode 9 : Link blocks to Freelist
         Opcode 10 :Unlink blocks from Freelist
         Opcode 11 :Undo to Apply Position Update (see opcode 8)
         Opcode 12 :Convert segment header to 6.2.x type
Layer 15 : Table Space -  KCOCOTTS     [ktt.h]
        Opcode 1 : Format deferred rollback segment header
        Opcode 2 : Add deferred rollback record
        Opcode 3 : Move to next block
        Opcode 4 : Point to next deferred rollback record
Layer 16 : Row Cache -  KCOCOQRC     
Layer 17 : Recovery (REDO) -  KCOCORCV     [kcv.h]
         Opcode 1 : End Hot Backup : This operation clears the hot backup
                    in-progress flags in the indicated list of files
         Opcode 2 : Enable Thread : This operation creates a redo record
                    signalling that a thread has been enabled
         Opcode 3 : Crash Recovery Marker
         Opcode 4 : Resizeable datafiles
         Opcode 5 : Tablespace ONline
         Opcode 6 : Tablespace OFFline
         Opcode 7 : Tablespace ReaD Write
         Opcode 8 : Tablespace ReaD Only
         Opcode 9 : ADDing datafiles to database
         Opcode 10 : Tablespace DRoP
         Opcode 11 : Tablespace PitR     
Layer 18 : Hot Backup Log Blocks -  KCOCOHLB     [kcb.h]
         Opcode 1 : Log block image
         Opcode 2 : Recovery testing
Layer 19 : Direct Loader Log Blocks - KCOCODLB     [kcbl.h]
         Opcode 1 : Direct block logging
         Opcode 2 : Invalidate range
         Opcode 3 : Direct block relogging
         Opcode 4 : Invalidate range relogging     
Layer 20 : Compatibility Segment operations - KCOCOKCK  [kck.h]
         Opcode 1 : Format compatibility segment -  KCKFCS
         Opcode 2 : Update compatibility segment - KCKUCS
Layer 21 : LOB segment operations - KCOCOLFS     [kdl2.h]
         Opcode 1 : Write data into ILOB data block - KDLOPWRI
Layer 22 : Tablespace bitmapped file operations -  KCOCOTBF [ktfb.h]
Opcode 1 : format space header - KTFBHFO
Opcode 2 : space header generic redo - KTFBHREDO
Opcode 3 : space header undo - KTFBHUNDO
Opcode 4 : space bitmap block format - KTFBBFO
Opcode 5 : bitmap block generic redo - KTFBBREDO
Layer 23 : write behind logging of blocks - KCOCOLWR [kcbb.h]
Opcode 1 : Dummy block written callback - KCBBLWR
Layer 24 : Logminer related (DDL or OBJV# redo) - KCOCOKRV [krv.h]
Opcode : common portion of the ddl - KRVDDL
Opcode : direct load redo - KRVDLR
Opcode : lob related info - KRVLOB
Opcode : misc info - KRVMISC
Opcode : user info - KRVUSER
         
      備註:該操作不包含undo vector, segment header的修改即使交易回滾,它也不會發生回滾。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9606200/viewspace-745681/,如需轉載,請註明出處,否則將追究法律責任。

相關文章