1. 程式人生 > >Oracle RedoLog-二進位制格式分析,檔案頭,DML,DDL

Oracle RedoLog-二進位制格式分析,檔案頭,DML,DDL

上篇文章,簡單介紹了 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