oracle 11g歸檔日誌研究_4

来源:http://www.cnblogs.com/linux-c/archive/2016/02/23/5209373.html
-Advertisement-
Play Games

change的內容,是oracle日誌轉化為SQL語句的核心,也是最麻煩,變化最多的地方。 先說opcode,opcode的含義網上隨便一搜有很多,真正對我有用的,只有增刪改,至於什麼搜索、索引等操作,我根本就不關心。 5.1:包含信息較多,每個增刪改一定對應一個有效的5.1,這個5.1中將包含原始


change的內容,是oracle日誌轉化為SQL語句的核心,也是最麻煩,變化最多的地方。

先說opcode,opcode的含義網上隨便一搜有很多,真正對我有用的,只有增刪改,至於什麼搜索、索引等操作,我根本就不關心。

5.1:包含信息較多,每個增刪改一定對應一個有效的5.1,這個5.1中將包含原始數據,用來在回滾(undo)時使用。另外還會有大量的5.1操作,目前我並不理解其他5.1操作的含義,並將這些我認為“無效”的5.1忽略。5.1的數據內容按照如下順序排列:

typedef struct ktudb {
    uint16_t siz;
    uint16_t spc;
    uint16_t flg;
    uint16_t unknown0;
    uint16_t xid0;
    uint16_t xid1;
    uint32_t xid2;
    uint16_t seq;
    uint8_t rec;
    uint8_t ufo;    //0x84: ktubu; 0x00: ktubl
}Redo_ktudb;
Redo_ktudb

這是5.1的change向量表之後的第一段數據,其中的xid也許可以作為txn的id,其他值我並不知道有什麼用。

typedef struct ktubl {
    uint32_t objn;
    uint32_t objd;
    uint32_t tsn;       //maybe
    uint32_t noname;    //maybe
    uint8_t opc0;
    uint8_t opc1;
    uint16_t slt;
    uint32_t unknown1;
    uint32_t unknown0;  //00 00 00 00
    uint32_t uba0;
    uint16_t uba1;
    uint8_t uba2;
    uint8_t unknown2;   //00
    uint32_t max_scn1;
    uint16_t max_scn0;
    uint16_t unknown3;
    uint32_t tx_scn1;
    uint16_t tx_scn0;
    uint16_t unknown4;
    uint32_t unknown5;  //00 00 00 00
    uint32_t txn_scn1;  //位置不確定
    uint16_t txn_scn0;
    uint16_t unknown6;  //00 00
    uint32_t brb;
    uint32_t unknown7;  //00 00 00 00
    uint8_t user;
    uint8_t bcl;    //maybe
    uint8_t idx;    //maybe
    uint8_t flg2;   //maybe
}Redo_ktubl;
Redo_ktubl

這是第二段,其中opc0.opc1應該為11.1,以對應我們的增刪改操作,其他值被我忽略。objd被我當做obj,在數據字典中查找對應項。雖然ktubl的結構被我定義成這樣,但實際數據是變長的,其可能只有24位元組,故可能使用時只有前幾個元素的值才是真實的。

typedef struct KTB {
    uint8_t op0;
    uint8_t unknown0[7];
    uint16_t xid0;
    uint16_t xid1;
    uint32_t xid2;
    uint32_t uba0;
    uint16_t uba1;
    uint8_t uba2;
    uint8_t unknown1;
    uint16_t unknown2;
    uint16_t scn0;
    uint32_t scn1;
}Redo_KTB;
Redo_KTB

本段也是變長的,事實上很多操作都會有KTB段,但是它們的結構卻不相同。

typedef struct KDO {
    uint32_t bdba;
    uint32_t hdba;
    uint16_t maxfr;
    uint8_t unop0;
    uint8_t unop1;  //maybe
    uint8_t itli;
    uint8_t unknown1[3];
    uint8_t slot;
    uint8_t unknown2[3];
}Redo_KDO;
Redo_KDO

本段也是變長的,好吧,看來5.1裡面沒有什麼是固定的了。

在這4段之後的數據,就屬於undo段了,其數據擺放格式都差不多,可以按照向量表將其內容列印分析。

 

5.2:包含的信息較少,可能應該作為一個事務(txn)的開始,但目前被我忽略。

typedef struct ktudh {
    uint16_t xid1;      //slt
    uint16_t unknown0;
    uint32_t xid2;      //sqn
    uint32_t uba0;
    uint16_t uba1;
    uint8_t uba2;
    uint8_t unknown1;
    uint16_t flg;
    uint16_t siz;
    uint8_t unknown3[12];
}Redo_ktudh;
Redo_ktudh

這似乎是5.2包含的唯一一段數據,固定為32個位元組,似乎5.2應該包含xid作為一個txn的標示,但它只包含了xid的一部分。

 

5.4:表示一個事務(txn)的結束,應該是意味著用戶提交了一次commit,可能應該與5.2對應。

typedef struct ktucm {
    uint16_t slt;
    uint16_t unknown0;
    uint32_t sqn;
    uint32_t srt;   //長度1-4
    uint32_t sta;   //長度1-4
    uint32_t flg;   //長度1-4
}Redo_ktucm;
Redo_ktucm

5.4的第一段數據,固定為20位元組。

typedef struct ktucf {
    uint32_t uba0;
    uint16_t uba1;
    uint8_t uba2;
    uint8_t unknown0;   //00
    uint16_t ext;
    uint16_t spc;
    uint16_t unknown1;
    uint16_t fbi;   //maybe
}Redo_ktucf;
Redo_ktucf

5.4的第二段數據,固定為16位元組。

之後5.4可能還會有其他數據,我並不知道那是什麼,並且,似乎最後一段總是以4位元組數據結束。

 

11.2:插入,對應insert語句。

11.2的第一段數據是KTB,其結構可以使用5.1的,但是長度卻不同,可能比5.1的要短。

typedef struct KDO_11_2 {
    uint32_t bdba;
    uint32_t hdba;
    uint16_t maxfr;
    uint16_t unknown0;
    uint8_t itli;
    uint8_t unknown1[3];
    uint16_t unknown2;
    uint16_t cc;
    uint8_t unknown3[20];
    uint16_t size_delt;
    uint8_t slot;
    uint8_t unknown4[10];
}Redo_KDO112;
Redo_KDO112

第二段是11.2的KDO。

從第三段開始,就是insert的內容了,每一段對應一個欄位,對於insert語句來說,所有的欄位都會在11.2中列出。

 

11.3:刪除,對應delete語句。

typedef struct KTB_11_3 {
    uint8_t op0;
    uint8_t unknown0[7];
    uint16_t xid0;
    uint16_t xid1;
    uint32_t xid2;
    uint32_t uba0;
    uint16_t uba1;
    uint8_t uba2;
    uint8_t unknown1;
    uint32_t zero0;
    uint32_t zero1;
    uint32_t zero2;
    uint32_t zero3;
    uint32_t zero4;
    uint32_t unknown2;
    uint32_t unknown3;
    uint32_t unknown4;
    uint16_t unknown5;
    uint16_t scn0;
    uint32_t scn1;
}Redo_KTB113;
Redo_KTB113

第一段,雖然名字都叫KTB,內容卻不一樣。

第二段是KDO,可以使用5.1的KDO結構。

 

11.5:修改,對應update語句。

typedef struct KTB_11_5 {
    uint8_t op0;
    uint8_t unknown0[7];
    uint32_t uba0;
    uint16_t uba1;
    uint8_t uba2;
    uint8_t unknown1;
}Redo_KTB115;
Redo_KTB115

第一段,又是一隻獨特的KTB。

typedef struct KDO_11_5 {
    uint32_t bdba;
    uint32_t hdba;
    uint16_t maxfr;
    uint16_t unknown0;
    uint8_t itli;
    uint8_t unknown1[3];
    uint8_t flag;
    uint8_t lock;
    uint8_t unknown2[2];
    uint8_t slot;
    uint8_t size;   //maybe
    uint8_t ncol;
    uint8_t nnew;
    uint8_t unknown4[5];
}Redo_KDO115;
Redo_KDO115

以及獨特的KDO。

第三段開始是update的數據,第三段本身,是類似於向量表的一個數組,只是它其中存儲的是要修改的數據欄位id-1。

 

11.17:對應於有LOB欄位的增、改操作,用來表示LOB欄位的總長度。還有一種不包含LOB長度的11.17,其意義不明,被我忽略。

typedef struct LOB_11_17 {
    uint16_t xid0;
    uint16_t xid1;
    uint32_t xid2;
    uint32_t OBJ;
    uint32_t unknown2;
    uint32_t unknown3;      //00
    uint32_t unknown4;      //00
    uint32_t lobsize;
    uint32_t unknown5;      //00
}Redo_LOB_11_17;
Redo_LOB_11_17

這是11.17的第三段,前兩段被我忽略掉了,我並不知道它們是什麼。並不是所有11.17都有這個結構,所以需要進行判斷,如果此段的長度不是32位元組,則認為這個11.17不是我們需要的。本段中lobsize就是本次操作的LOB欄位的總長度。

 

19.1:對應於有LOB欄位的增、改操作,存儲著LOB欄位的內容,目前我所操作的oracle 11g,會將LOB切割成8168-36(LOB頭)=8132位元組的塊,每塊分別放在一個19.1中。LOB的總長度需要通過11.17獲取,然後通過19.1獲取LOB數據。LOB頭格式:

typedef struct LOB_19_1_1 {
    uint32_t unknown0;
    uint32_t unknown1;
    uint16_t unknown2;
    uint32_t lob_set;
    uint16_t unknown3;
    uint32_t seq;           //2 or 4 byte, lob編號, 1 to n
    uint32_t unknown5;      //00
    uint32_t subseq;        //2 or 4 byte, lob分段編號, 0 to n
    uint32_t unknown7;
    uint32_t unknown8;      //00
}Redo_LOB_19_1;
Redo_LOB_19_1

LOB頭中有2個編號,這兩個編號表示LOB的排列順序,而且,由於insert和update使用的方式不同(java腳本、sqldeveloper等),LOB數據可能有重覆(此時LOB第1個編號會+1,第2個編號會從0開始)。

 

以上是增刪改對應的基本數據結構。以下進行簡單總結說明:

我們進行的是增刪改操作,即11.2、11.3、11.5是我們真正操作的內容。

如果我們的增、改操作帶有LOB欄位,則會出現11.17和19.1。

每個操作(指的是11.2、11.3、11.5),一定有其對應的5.1,其中含有undo所需的內容。

11.3最簡單,因為其中沒有需要解析的數據,只要通過5.1的undo段確定所在行即可,而通常只需要一個主鍵就解決了。

11.2中等,需要插入的數據都在11.2的數據段,其5.1的undo段是空的,因為插入的undo就是刪除。

11.5最複雜,需要修改的數據在11.5的數據段,而需要定位的行則必須從其對應的5.1的undo段解析,undo段存的其實就是11.5中對應欄位的原值。

 

程式運行示例:

程式指定數據字典為dictionary.ora,歸檔日誌文件為o1_mf_1_3279_brn6w2fm_.arc,程式運行結果非常巨大,只貼出其中一小部分。

解析數據字典,得出用戶名、表名、欄位名。從日誌文件只能解出對應obj即id,需要通過數據字典查到名稱。其中數據字典中的欄位id從1開始,日誌文件中從0開始,故需對日誌文件中的欄位id+1,其他id不需要。

以5.2、5.1開始,5.4結束,中間11.2表示insert操作。圖片中的ERR是DEBUG輸出,請無視~~

解析結果存為SQL語句。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 回到目錄 一些概念 分區表在oracle和sqlserver中都上存在的,當數據表的數據量過大時,上千萬,上億的數據,在進行數據查詢時需要顯得比較慢,性能很差,這時是時候引入分區表了,分區表顧名思義,就是把物理表用一些文件NDF進行分塊存儲,以緩減IO的壓力,因為當你的SQL文件過大的,這其實對系統
  • 一個小時內學習SQLite資料庫 2012-05-11 10:24 紅薯 OSCHINA 字型大小:T | T SQLite 是一個開源的嵌入式關係資料庫,實現自包容、零配置、支持事務的SQL資料庫引擎。 其特點是高度便攜、使用方便、結構緊湊、高效、可靠。 與其他資料庫管理系統不同,SQLite 的安裝
  • 這裡僅僅用到了一種方式而已,把資料庫文件備份到磁碟然後在恢復. /* 2: 通過SQL 語句備份資料庫 3: */ 4: BACKUP DATABASE mydb 5: TO DISK ='C:\DBBACK\mydb.BAK' 6: --這裡指定需要備份資料庫的路徑和文件名,註意:路徑的文件夾是必
  • Oracle 中對中文欄位進行排序通常有三種方式 1)按筆畫排序 select * from Table order by nlssort(columnName,'NLS_SORT=SCHINESE_STROKE_M') 2)按部首排序 select * from Table order by nl
  • 出處:http://www.cnblogs.com/cmsdn/archive/2012/04/25/2469568.html 以下SQL以防以後還需用到,特此備份 刪除一條留言信息會級聯刪除回覆信息,這時我們需要用到事務,如下SQL 1 ALTER PROCEDURE [dbo].[proc_tb
  • SQL Server代理是所有實時資料庫的核心。代理有很多不明顯的用法,因此系統的知識,對於開發人員還是DBA都是有用的。這系列文章會通俗介紹它的很多用法。 在這一系列的上一篇,我們看了使用代理帳戶模仿Windows安全上下文完成作業步驟的工作。大多數子系統支持代理賬戶,同時子系統限制代理賬戶, 要
  • 因為這篇文章寫的比較長一些,我就將總結先列出來 總結 1. 除了WHERE條件外,JOIN欄位除了記得建立索引,也要註意到選擇性的高低,如果真的找不到可用的欄位,可以考慮在兩邊關聯的表上加入super eky,再做JOIN如果單純想測試這個欄位的選擇性,可以透過這個語法SELECT 1 / CAST
  • 今天繼續發整理學習篇~查詢5步走,一步一回頭~ 通常來說查詢的順序呢~從 From -> Where -> Group By -> Select -> Order By 一般來說我們一個語句從查詢開始,藉助了 AdventureWorks2014 來舉例 SELECT TOP 50 a.Person
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...