Oracle實時數據抽取項目問題總結
項目背景介紹
項目主要是將Oracle、MySQL、SQLServer、Db2等其他數據庫的實時變更數據同步到其他異構數據庫中。本篇文章主要是討論oracle的實時采集,通過Logminer捕獲歸檔日志,然后將提取后的數據推送到Kafka中。
項目使用的技術框架
使用的核心框架:https://github.com/debezium/debezium 用於捕獲歸檔日志,然后推送到kafka中。
Debezium框架是基於Kafka Connect實現的,分為source端和sink端。
source: 負責將源庫的數據放入kafka中;
sink: 負責將kafka的數據落入目標庫中;
source和sink的調度管理統一交給kafka connect來負責。
如何獲取歸檔日志
Debezium實現的Oracle source端,將數據同步到kafka中,有Logminer和XStream兩種實現方式,其中Logminer是oracle數據庫自帶的,不需要額外收費;而XStream需要額外收費的。因此,今天主要介紹的是Logminer的方式獲取歸檔日志。
Logminer獲取歸檔日志的步驟
這里只介紹一個大概的步驟,具體詳細步驟請參考Oracle官方文檔,里面有比較詳細的步驟。
- 首先需要開啟oracle數據庫歸檔日志;
- 使用Logminer程序
DBMS_LOGMNR.ADD_LOGFILE
增加需要采集的日志,這一步很重要,也是今天問題的核心。 - 調用開始采集
DBMS_LOGMNR.START_LOGMNR
程序; - 查詢
V$LOGMNR_CONTENTS
視圖,從而獲取歸檔文件中的數據; - 調用
DBMS_LOGMNR.END_LOGMNR
程序結束.
Oracle歸檔日志和重做日志
因為實時數據采集主要是作用在歸檔日志和重做日志上,如果對這兩種日志不理解,將導致Logminer出現的錯誤無法有一個清晰的認知,從而無法解決現場實際面臨的各種問題。
重做日志
也被稱為redo log,主要是用來進行數據庫恢復的,你對數據庫表的任何數據操作,都會首先將變更寫入重做日志中,用來在數據庫宕機時能及時恢復數據,里面記錄了數據的詳細變更記錄。默認數據庫會有3個重做日志文件,可以通過查詢V$LOGFILE獲取。這3個重做日志文件是輪流使用的,當第一個用滿后將切換到第二個、當第二個用滿之后切換到第三個,當第三個用滿之后切換到第一個,切換之后目標重做日志就被覆蓋了,也就是丟失了。例如當第一個用滿后將切換到第二個,那么原來第二個重做日志上的數據就丟失了。當然,這個重做日志的文件大小和個數都是可以配置的。
特點:及時寫入,自動循環覆蓋
歸檔日志
歸檔日志主要是重做日志的一個備份,也可以用來進行數據的恢復,也可以用來進行數據庫的同步。由於重做日志會循環使用,並且還會出現覆蓋丟失的情況,因此,需要將重做日志放到別的地方進行備份存儲,這也就誕生了歸檔日志。歸檔日志默認是不開啟的,需要配置數據庫才能使用,並且需要占用許多存儲,因此需要及時的清理。重做日志會定時的存儲成歸檔日志,並且在切換的時候也會存儲到歸檔日志中,防止重做日志丟失。
特大:自動觸發寫入、可永久存儲
問題:ora-01291: missing logfile
有了Logminer和歸檔日志和重做日志的簡單介紹之后就可以進入今天的正題了,我們在實時抽取oracle歸檔日志的時候發現,當數據量很大的時候經常會出現oracle錯誤:ora-01291: missing logfile,提示找不到重做日志文件了。
首先我們需要分析Logminer的第二步:DBMS_LOGMNR.ADD_LOGFILE,這一步不僅需要將歸檔日志添加到Logminer引擎中,還需要將重做日志也需要添加進來,因為歸檔日志的數據並不是及時的,需要配合歸檔日志 + 重做日志才能保證及時性,但是重做日志又有被覆蓋的可能,因此就會出現ora-01291錯誤。了解了問題原因,那么我們如何解決問題呢?既然只有在數據量很大的時候才會出現,那么我們可以將重做日志的個數增加到10個,每個文件大小增加到5G。這個調整需要謹慎操作,官方的說法是最好將重做日志的切換時間控制在半小時左右。這樣就不會出現ora-01291的錯誤了,因為重做日志的切換頻率降低了、文件個數也增加了。例如Logminer目前正在讀取重做日志5 + 歸檔日志,只有當oracle此時立馬把 重做日志5,6,7,8,9,0,1,2,3,4,5(以10個重做日志為例)全部寫滿才會導致重做日志5丟失,而此時每個操作日志的大小為5G,總共需要寫入50G的數據,你不可能那么快寫入50GB,當你寫入的時候Logminer已經讀取完了,因此就不會再出現找不到重做日志的問題了。
問題:日志定位耗時
當數據庫產生了大量歸檔日志的時候,Logminer需要定位到某一個表的起始SCN點很耗時。這個問題可以調整配置來實現,Debezium有大量的配置用來控制SCN點的增量范圍和每次獲取時間設置等,需要根據自身的場景進行合理調整。
配置名 | 默認值 | 描述 |
---|---|---|
log.mining.batch.size.min |
1000 |
The minimum SCN interval size that this connector attempts to read from redo/archive logs. Active batch size is also increased/decreased by this amount for tuning connector throughput when needed. |
log.mining.batch.size.max |
100000 |
The maximum SCN interval size that this connector uses when reading from redo/archive logs. |
log.mining.batch.size.default |
20000 |
The starting SCN interval size that the connector uses for reading data from redo/archive logs. |
log.mining.sleep.time.min.ms |
0 |
The minimum amount of time that the connector sleeps after reading data from redo/archive logs and before starting reading data again. Value is in milliseconds. |
log.mining.sleep.time.max.ms |
3000 |
The maximum amount of time that the connector ill sleeps after reading data from redo/archive logs and before starting reading data again. Value is in milliseconds. |
log.mining.sleep.time.default.ms |
1000 |
The starting amount of time that the connector sleeps after reading data from redo/archive logs and before starting reading data again. Value is in milliseconds. |
log.mining.sleep.time.increment.ms |
200 |
The maximum amount of time up or down that the connector uses to tune the optimal sleep time when reading data from logminer. Value is in milliseconds. |
log.mining.view.fetch.size |
10000 |
The number of content records that the connector fetches from the LogMiner content view. |
log.mining.archive.log.hours |
0 |
The number of hours in the past from SYSDATE to mine archive logs. When the default setting (0 ) is used, the connector mines all archive logs. |