场景:现场库到前置库
思考1:使用触发器?
1、侵入性解决方案
2、需要时各种配置,不需要时又是各种配置
Change Data Capture:捕捉变化的数据,通过日志监测并捕获数据库的变动(包括数据或数据表的插入,更新,删除等),将这些变更按发生的顺序完整记录下来,写入到消息中间件中或者通过其他途径分发出去。
与触发器相比,通过日志监控的好处:
- 1、对原库基本无侵入性,不需要像触发器一样,对原库进行操作。
- 2、可以针对整库或者库中的表进行监控,比触发器更加灵活高效,避免监控表比较多的情况的频繁的建触发器
思考2:为何不用debezium、flinkx
首先debezium,也可以利用logminer去实现,但是他是类似kafka的一个插件,调试麻烦,而且使用复杂。
flinkx也是利用flink、logminer来实现了,但是同样存在代码复杂,使用有了问题不好调试,难度比较大,而且flinkx利用logminer实现的方案还不支持二进制和大字段。
我们想想场景,我们假如做利用logminer去实现增量,不太可能上来就是数据量非常庞大的大场景,所有有没有一般的单机版的可以实现场景,可以进行调试,可以进行原理分析,等上了量就用debezium或者flinkx呢,这就是我想去做这个开源的目的,借鉴了debezium和flinkx的一些思想和方案,实现了一个简易的框架,同时也可以在此框架上做很多事情。针对场景发展。
实现原理
概念
Oracle:通过开源logminer进行日志分析,支持大字符串,二进制。
目前只针对在线日志分析,离线的由于需要考虑log大小等,留给以后处理。
开启归档日志,这边步骤主要是为了能够使用logminer
关于logminer:
所有对用户数据和数据字典的改变都记录在Oracle的Redo Log中,因此,Redo Log包含了所有进行恢复操作所需要的信息。但是,原始的Redo Log文件无法看懂,所以,Oracle从8i以后提供了一个非常有用的分析工具,称为LogMiner。使用该工具可以轻松获得Redo Log文件(包含归档日志文件)中的具体内容。
logminer执行
通过不断的执行此语句进行把内容找出来
SELECT
scn,
timestamp,
operation,
operation_code,
seg_owner,
table_name,
sql_redo,
sql_undo,
xidusn,
xidslt,
xidsqn,
row_id,
rollback,
start_scn,
commit_scn,
csf
FROM
v$logmnr_contents
WHERE
scn >= ?
AND scn < ?
and ( ((SEG_OWNER='EPOINT' and TABLE_NAME='BASEINFO') or (SEG_OWNER='EPOINT' and TABLE_NAME='ACCOUNT')) or OPERATION='COMMIT' or OPERATION='ROLLBACK')
如何处理二进制
二进制由于oracle是通过存储过程来存储的,所以我们这边在代码中做一些处理,让二进制字段和他所在sql进行一个关联。
例如insert语句:
insert into "EPOINT"."BASEINFO"("ROWGUID","NAME","BIRTHDAY","AGE","ADDRESS","INFO","IMAGE") values ('3fb6529d-81d3-4639-b591-1115edb3b06b','寿伊纨',TIMESTAMP ' 1989-07-06 15:45:56',87,UNISTR('\79CB\9633\8DEF84\53F7-16-5'),EMPTY_CLOB(),EMPTY_BLOB())
EMPTY_CLOB(),EMPTY_BLOB()就是下面截图中的数据,我们需要解析出来然后关联到insert into的语句上。
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')
架构图
启动
目前一条带大字段的会拆为2条语句,内部没有做合并,这个可以考虑未来做掉
注意点
1、数据和位点在一个结构中,这样可以保证有数据就有位点,可以精准定位数据现在跑到哪里了。
2、目前一条带大字段的会拆为2条语句,内部没有做合并,这个可以考虑未来做掉。
3、我们logminer扫描的时候会找最后一条commit的位点,commit证明到此时这些数据都已经完整记入日志,其他数据我们会放入下个流程。即使commit后面的数据入了全局map,我们还会把他剔除,放入下个流程。
4、logminer设置了上限是10000,避免内存问题等。这个步长可以设置
github地址: