oracle實現通過logminer實現日志抓取分析


場景:現場庫到前置庫。

思考:使用觸發器?

1、侵入性解決方案

2、需要時各種配置,不需要時又是各種配置

Change Data Capture:捕捉變化的數據,通過日志監測並捕獲數據庫的變動(包括數據或數據表的插入,更新,刪除等),將這些變更按發生的順序完整記錄下來,寫入到消息中間件中或者通過其他途徑分發出去。

與觸發器相比,通過日志監控的好處:

  • 1、對原庫基本無侵入性,不需要像觸發器一樣,對原庫進行操作。

  • 2、可以針對整庫或者庫中的表進行監控,比觸發器更加靈活高效,避免監控表比較多的情況的頻繁的建觸發器

說明

關於logminer:

所有對用戶數據和數據字典的改變都記錄在Oracle的Redo Log中,因此,Redo Log包含了所有進行恢復操作所需要的信息。但是,原始的Redo Log文件無法看懂,所以,Oracle從8i以后提供了一個非常有用的分析工具,稱為LogMiner。使用該工具可以輕松獲得Redo Log文件(包含歸檔日志文件)中的具體內容。

關於代碼:全部寫到一個java方法下,主要演示所有過程,關鍵問題處理,封裝留給你們自己進行。

關於參考:主要參考了debezium和一些國外開源的實現,但是這些都沒有支持clob大字段和blob二進制字段,同時也沒考慮一些特殊情況,我在平時的測試積累中解決了此塊的內容,故一起開源分享出來。

Github地址

https://github.com/nengm/OracleCDCByLogminer

前置步驟

Oracle:通過開源logminer進行日志分析,支持大字符串,二進制。

目前只針對在線日志分析,離線的由於需要考慮log大小等,留給以后處理。

開啟歸檔日志,這邊步驟主要是為了能夠使用logminer

以數據庫系統管理員sys as sysdba登錄
SQL> shutdown immediate; 關閉數據庫
SQL> startup mount; 啟動數據庫到mount狀態
SQL> alter database archivelog; 啟動歸檔模式
SQL> alter database open;啟動數據庫
SQL> alter system switch logfile;切換日志文件
查看數據字典表或視圖權限
GRANT SELECT_CATALOG_ROLE TO [用戶名];
執行系統所有包權限
GRANT EXECUTE_CATALOG_ROLE TO [用戶名];
創建會話權限
GRANT CREATE SESSION TO [用戶名];
選擇任何事務的權限
GRANT SELECT ANY TRANSACTION TO [用戶名];

對於12c及以上,還需要對pdb用戶進行一些設置,具體遇到再百度下。

分析過程

1、拿到當前最大位點

img

2、開啟logminer分析

如果ENDSCN和STARTSCN沒有超過步長,ENDSCN就拿當前的最大位點。

begin
DBMS_LOGMNR.START_LOGMNR(
STARTSCN => 586613478,
ENDSCN => 586613490,
OPTIONS =>
DBMS_LOGMNR.SKIP_CORRUPTION
+DBMS_LOGMNR.NO_SQL_DELIMITER
+DBMS_LOGMNR.NO_ROWID_IN_STMT
+DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG
+DBMS_LOGMNR.CONTINUOUS_MINE
+DBMS_LOGMNR.COMMITTED_DATA_ONLY
+DBMS_LOGMNR.STRING_LITERALS_IN_STMT
);
end;

3、通過數據字典得到表的數據類型

代碼中的dictionary.sql

4、根據配置的白名單進行信息刪選

SELECT
*
FROM
  V$LOGMNR_CONTENTS
WHERE(SEG_OWNER = 'EPOINT' AND TABLE_NAME = 'BASEINFO' AND COMMIT_SCN >=0)

img

5、分析

1、insert語句(帶大字段和圖片)

大字段和圖片都通過存儲過程得到。

img

我們根據csf看是否超過4000個字節,如果超過csf為0,我們把所有的sql先組裝到一起,然后通過信息組裝出一個guid,存入map,這樣后面就能找到對應的EMPTY_CLOB()對應的值了。

//用xid、ownerName、tableName、columnString唯一標識當前二進制字段的guid
//#!>-<!#為分隔符
//例如:99001800E16A0000#!>-<!#EPOINT#!>-<!#BASEINFO1#!>-<!#IMAGE

2、update語句(帶大字段和圖片)

update "EPOINT"."BASEINFO" set "NAME" = '蘇愛毓', "BIRTHDAY" = TIMESTAMP ' 1977-03-17 17:22:59', "AGE" = 3, "ADDRESS" = UNISTR('\6FB3\95E8\516B\885718\53F7-8-6') where "ROWGUID" = 'b73af60a-cdda-4702-8f28-0d707c0245a1' and "NAME" = '法貞鳳' and "BIRTHDAY" = TIMESTAMP ' 1978-04-16 09:21:46' and "AGE" = 61 and "ADDRESS" = UNISTR('\8BF8\57CE\5927\53A674\53F7-6-8')

下面緊接着是他要處理的大字段和二進制。

程序中通過下面的guid判斷是否是一批數據,然后把檢測到的大字段或者二進制與之關聯。

//用xid、ownerName、tableName、columnString唯一標識當前二進制字段的guid
//#!>-<!#為分隔符
//例如:99001800E16A0000#!>-<!#EPOINT#!>-<!#BASEINFO1#!>-<!#IMAGE

注意:

我們再測試下,讓startscn加1

img

可以看到無法分析出數據了,所以我們程序需要處理掉這種情況,遇到這種情況最簡單的辦法就是startscn要往回退一點,也注意不能形成死循環

其實主要是通過這些進行流程的分析處理,里面會遇到很多的坑。

測試實現

配置:由於測試整個過程,暫時單表,多表只要改造下。

1、配置

img

2、啟動

img

 

3、插入一條數據

主要在11g在測試,12c做了兼容,而且要使用cdb賬戶

11g

img

插入mysql中

img

5、更新

oracle

img

更新完mysql

img

6、插入2000條測試

oracle

img

mysql目標數據庫

img

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM