? ? 接到一個(gè)數(shù)據(jù)采集的需求,要求從一個(gè)遠(yuǎn)程數(shù)據(jù)庫中將固定幾張表的數(shù)據(jù)采集到本地?cái)?shù)據(jù)庫中,進(jìn)行數(shù)據(jù)清洗工作,同時(shí)將缺失的數(shù)據(jù)補(bǔ)全。ps:請忽略本地?cái)?shù)據(jù)庫,因?yàn)楝F(xiàn)實(shí)原因生產(chǎn)庫在短期內(nèi)不能上線,遠(yuǎn)程數(shù)據(jù)庫不可能同意建立dblinlk的請求,所以數(shù)據(jù)庫腳本層面上解決問題的思路被我拋棄了,而且清洗過程中用到了一些java的腳本,數(shù)據(jù)庫程序中沒有現(xiàn)成的函數(shù),所以最終結(jié)果是我需要寫一個(gè)采集程序,定期執(zhí)行采集腳本。
? ? ? ? 采集比較簡單,直接連接遠(yuǎn)程數(shù)據(jù)庫,用jpa、mybaits等成熟的產(chǎn)品直接寫查詢sql就行了,這里我采用的架構(gòu)為beetlsql,理由請自行百度吧。
? ? 采集相關(guān)的日志表設(shè)計(jì)
LOG_ID ? ? ? ? ? ? ? ? ? ? NUMBER(17) ? ? ? ? ? ? ? ?主鍵
TABLE_NAME ? ? ? ? ? VARCHAR2(200) ? ? ? ? ?表名
DA_TIME ? ? ? ? ? ? ? ? ? DATE ? ? ? ? ? ? ? ? ? ? ? ? ? ?抽取時(shí)間
BATCH_NUMBER ? ? NUMBER(15) ? ? ? ? ? ? ? ?批次號
DA_STATUS ? ? ? ? ? ? ?NUMBER(1) ? ? ? ? ? ? ? ? 1、開始抽取2、抽取成功3、抽取失敗回滾成功
DA_COUNT ? ? ? ? ? ? ? NUMBER(10) ? ? ? ? ? ? ? 抽取數(shù)據(jù)條數(shù)
????主鍵,不解釋了,抽取時(shí)記錄抽取時(shí)間,開始抽取執(zhí)行查詢sql前生成抽取時(shí)間,生成批次號,維護(hù)表名,生成一條上表的記錄,狀態(tài)為1,表示開始抽取。
? ? 執(zhí)行查詢sql,將上一步中生成的批次號添加至查詢的列上作為備用,查詢結(jié)果信息為源表的列1,列2,。。。列n,批次號。
? ? 獲取執(zhí)行的結(jié)果信息,執(zhí)行insert方法插入本地?cái)?shù)據(jù)庫表中,并進(jìn)行trycatch,當(dāng)插入執(zhí)行成功時(shí),將第一步生成的記錄的狀態(tài)更新為抽取成功(2),執(zhí)行失敗的時(shí)候根據(jù)上述生成的批次號,到本地?cái)?shù)據(jù)庫表中刪除該批次號對應(yīng)的數(shù)據(jù),然后將日志狀態(tài)更新為3,表示抽取失敗,回滾成功。
? ? 之所以不在執(zhí)行成功的時(shí)候直接寫入日志的原因是程序采集需記錄每次采集的時(shí)間,采集成功的狀態(tài),采集的數(shù)據(jù)量,如果執(zhí)行成功才寫入日志會導(dǎo)致失敗的日志無法記錄,同時(shí)也使下次抽取時(shí)間的準(zhǔn)確性提高,不會漏采數(shù)據(jù)。
? ? 比如一開始直接執(zhí)行采集,成功,寫入日志成功,失敗寫入日志失敗,那當(dāng)我執(zhí)行采集的時(shí)間是0:0:0,抽取sql查詢需耗時(shí)10s,插入需耗時(shí)20s,那么如果在第一次采集之后5s左右有執(zhí)行了一次采集,那么采集程序是無法識別上次采集時(shí)間的,因?yàn)樯洗尾杉瘯r(shí)間實(shí)在10s查詢,20s插入之后才入庫的。這回造成采集程序的重復(fù)采集,對數(shù)據(jù)的唯一性,準(zhǔn)確性打上了問號。而在采集查詢之前先寫入日志的話,下次采集會讀取最新的狀態(tài)為1或2的采集時(shí)間,將其作為上次采集時(shí)間,從而避免上述的情況的產(chǎn)生。