Oracle RedoLog-二進位格式分析,文件頭,DML,DDL
- 2021 年 1 月 8 日
- 筆記
- oracle redolog
上篇文章,簡單介紹了 RedoLog 是什麼,以及怎麼從 Oracle Dump 二進位日誌。接下來,分析下 Redo Log 二進位文件的格式,主要包括:文件頭,重做日誌頭,DML-INSERT 操作,DDL-CREATE 操作。
Redo Log 二進位文件中,採用的是小端序位元組序。
原文鏈接://www.chuonye.com/archives/oracle-redolog-format.html
1. File Header
文件頭,佔用第一個塊。Oracle 中許多二進位的數據和日誌文件都有相似的格式,在線日誌 Redo Log 文件也是如此。下圖是 RedoLog 文件開始的前 80 位元組。

File Type
前 2位元組 表示文件類型,區分不同的 Oracle 文件,比如,在 10g 版本中:
0xA2表示數據文件,Data File0xC2表示控制文件,Control File0x22表示重做日誌文件,Redo Log File
Oracle 資料庫其實就是由一堆文件組成的。
Block Size
偏移量 20,長度 2位元組,存儲的是塊大小,它的值是固定的,只會因作業系統而不同。在 Windows, Linux 和 Solaris 上,塊大小為 512位元組–0x0200,而 HP-UX 的塊大小為 1024。
另外,每個塊都有一個 16位元組 的塊頭,稍後會介紹它。
Number of Blocks
偏移量 24,長度 4位元組,存儲的是文件中的塊數,不包括文件頭本身使用的塊,可以這樣計算出整個文件的大小:
(0x00019000 + 1) * 512 = 52429312 (50MB)
Magic
魔數只是文件標識,用來檢查是否是 Oracle 文件。
Block Header
每個塊都有一個 16位元組 的頭部,即使一個 Redo Record 橫跨多個塊,解析時這一點尤為重要。

上圖黃色指示的是一個頭部示例,每個塊頭都是以簽名 0x0122 開頭,其中:
- 偏移量
4,長度4位元組,存儲的是塊在文件中的編號 - 偏移量
8,長度4位元組,存儲的是日誌序號 - 偏移量
12,長度1位元組,存儲的是 Record 在該塊內的位元組偏移量
這三個值正好是 Record 的 RBA 內容。
最後偏移量 14,長度 2位元組,存儲的是校驗和,用於驗證數據是否完整,驗證的邏輯這裡就不記錄了,感興趣的可以在上篇描述的 PDF 文件內找到。
2. Redo Log Header
重做日誌頭,佔用第二個塊。這裡包含的資訊就多了,如資料庫SID,資料庫版本和開始記錄的時間等。

3. Redo Record
Redo Record 包含一個 SCN 中的所有操作,由一個頭和一個或多個 change vector 組成。比如往一個有索引的表中插入一條數據,會創建以下內容:
- 為 INSERT 操作,分別創建
redo change和undo change - 為索引改動,分別創建
redo change和undo change - 一個事務開始 change,一個事務提交 change
其中的每個 Change 都有一個操作碼,用於區分,常見的操作碼:
- 5.1:撤銷修改 - Undo Record
- 5.2:事務開始
- 5.4:事務提交 - Commit
- 11.2:插入一行數據
- 11.3:刪除一行數據
- 11.11:插入多行數據
- 11.19:更新多行數據
- 10.2:插入一個索引 - INSERT LEAF ROW
- 10.4:刪除一個索引 - DELETE LEAF ROW
- 13.1:申請空間 - CREATE TABLE 後
- 24.1:DDL 操作
4. DML-INSERT
增刪改是資料庫基本操作,下圖顯示的是一個插入操作 Record 轉成十六進位的資訊。

Block 頭的第 12 個位元組 0x10,表示 Record 開始位元組在偏移量 16位元組 處;
Record 開始的前 2位元組 表示長度,最大為 65536位元組,因此它可能需要多個 block 存儲。這裡長度是 0x01A8=424 一個 block 足以存儲。之後的第4個位元組是 Record 頭長度標識 VLD,具體數值取決於 Record 類型,這裡的 0x0D 表示頭長度為 0x44=68;
跳過 0x44位元組 就能找到第一個 Change Vector,操作碼是 0x0B02 - 11.2,即 INSERT 操作。在操作碼後的第22位元組,可以找到插入對象的ID,這裡是 0x0057 - 87,在字典表 dba_objects 查詢 data_object_id=87 的記錄可知插入的表為 SYS.SYSAUTH$;
跳過 0x44+0x18位元組,開始的2位元組 0x000C=12 表示第一個 Change 的元素長度列表的長度,元素長度佔用 2位元組,12位元組表示除頭2位元組外,總共有 (12-2)/2=5 個 長度元素,這意味著插入了 3個 欄位內容。
0x0014和0x0031:這兩個值是半固定的,表示 KTB 和 KDO 的長度0x0002:表示插入第一列的數據位元組數為2位元組0x0002:表示插入第二列的數據位元組數也為2位元組0x0003:表示插入第三列的數據位元組數為3位元組
上面的長度計算的是實際長度,但在計算偏移量是都需要 4位元組對齊。跳過指定的位元組後,可以得到三個欄位的值為:
0xC102:表示的內容為 數字 10xC105:表示的內容為 數字 40xC20931:表示的內容為 數字 848
結合 SYSAUTH$ 的欄位就能還原 SQL:
SQL> INSERT INTO SYS.SYSAUTH$ (GRANTEE#,PRIVILEGE#, SEQUENCE#) VALUES (1,4,848);
再往後有兩個 Change,0x0502 和 0x0501。0x0502 可以解析出此次事務的 XID;0x0501 是撤銷操作,INSERT 對應的就是 DELETE。
5. DDL-CREATE
雖然 DDL 語句已寫入 Redo Log 文件中,但是在使用 ALTER SYSTEM DUMP LOGFILE 命令後,結果中沒有語句,內容如下:
REDO RECORD - Thread:1 RBA: 0x000082.0000febf.002c LEN: 0x00f4 VLD: 0x01
SCN: 0x0000.003a061f SUBSCN: 1 03/13/2007 13:55:41
CHANGE #1 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ: 0 OP:24.1
操作碼 24.1 表明是 DDL 操作。從 RBA 中,可以看到塊編號為 0x0000febf (65215),塊大小為 512,所以該操作在二進位文件的偏移量為 512*65215=33390080 ,十六進位為 0x01FD7E00:

可以清楚的看到 DDL 語句:
create user wiggywiggywiggy identified by VALUES '2FA1749D698AD874'
對應二進位格式映射資訊是:

6. 總結
本文簡單描述了二進位格式具體是什麼,實際分析的時候也是這樣,把二進位文件打開轉成 16進位顯示,一個位元組一個位元組的分析。如果做過網路編程,特別是 TCP 私有協議設計和解析,應該很容易理解。
下一篇會介紹解析的一些問題,比如 Record 頭長度怎麼計算,Rowid 怎麼計算等等。

