Oracle RedoLog-二進位制格式分析,檔案頭,DML,DDL
阿新 • • 發佈:2021-01-08
上篇文章,簡單介紹了 RedoLog 是什麼,以及怎麼從 Oracle Dump 二進位制日誌。接下來,分析下 Redo Log 二進位制檔案的格式,主要包括:**檔案頭**,**重做日誌頭**,**DML-INSERT 操作**,**DDL-CREATE 操作**。
Redo Log 二進位制檔案中,採用的是**小端序**位元組序。
原文連結:https://www.chuonye.com/archives/oracle-redolog-format.html
## 1. File Header
檔案頭,佔用第一個塊。Oracle 中許多二進位制的資料和日誌檔案都有相似的格式,線上日誌 Redo Log 檔案也是如此。下圖是 RedoLog 檔案開始的前 80 位元組。
![file-header][1]
### **File Type**
前 `2位元組` 表示檔案型別,區分不同的 Oracle 檔案,比如,在 10g 版本中:
- `0xA2` 表示資料檔案,Data File
- `0xC2` 表示控制檔案,Control File
- `0x22` 表示重做日誌檔案,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 橫跨多個塊,解析時這一點尤為重要。
![block-header][2]
上圖黃色指示的是一個頭部示例,每個塊頭都是以簽名 `0x0122` 開頭,其中:
- 偏移量 `4`,長度 `4位元組`,儲存的是塊在檔案中的**編號**
- 偏移量 `8`,長度 `4位元組`,儲存的是**日誌序號**
- 偏移量 `12`,長度 `1位元組`,儲存的是 Record 在該塊內的**位元組偏移量**
這三個值正好是 Record 的 RBA 內容。
最後偏移量 `14`,長度 `2位元組`,儲存的是**校驗和**,用於驗證資料是否完整,驗證的邏輯這裡就不記錄了,感興趣的可以在上篇描述的 PDF 檔案內找到。
## 2. Redo Log Header
重做日誌頭,佔用第二個塊。這裡包含的資訊就多了,如資料庫SID,資料庫版本和開始記錄的時間等。
![redolog-header][3]
## 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 轉成十六進位制的資訊。
![redolog-header][4]
**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`:表示的內容為 **數字 1**
- `0xC105`:表示的內容為 **數字 4**
- `0xC20931`:表示的內容為 **數字 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-location][5]
可以清楚的看到 DDL 語句:
```
create user wiggywiggywiggy identified by VALUES '2FA1749D698AD874'
```
對應二進位制格式對映資訊是:
![ddl-format][6]
## 6. 總結
本文簡單描述了二進位制格式具體是什麼,實際分析的時候也是這樣,把二進位制檔案開啟轉成 16進位制顯示,一個位元組一個位元組的分析。如果做過網路程式設計,特別是 TCP 私有協議設計和解析,應該很容易理解。
下一篇會介紹解析的一些問題,比如 Record 頭長度怎麼計算,Rowid 怎麼計算等等。
[1]: https://img2020.cnblogs.com/blog/1424165/202101/1424165-20210107213811618-1791528646.gif
[2]: https://img2020.cnblogs.com/blog/1424165/202101/1424165-20210107213822161-518093472.gif
[3]: https://img2020.cnblogs.com/blog/1424165/202101/1424165-20210107213829017-833561050.gif
[4]: https://img2020.cnblogs.com/blog/1424165/202101/1424165-20210107213835721-1775692699.gif
[5]: https://img2020.cnblogs.com/blog/1424165/202101/1424165-20210107213842275-1736206411.gif
[6]: https://img2020.cnblogs.com/blog/1424165/202101/1424165-20210107213851953-75070