触发器迁移数据和MV的原理相同,通过在源表创建Trigger,记录源表的DML操作日志,然后通过存储过程同步DML受影响的记录,达到目标表和源表数据一致的效果。此方法只是对Prebuilt
MV操作的一个补充。物化视图/在线重定义对DML频繁的大表进行处理时,存在一个弊端,主要是在全量初始化这个步骤上,比如:
本应该多块扫描,直接路径读效率很高的,但由于个别数据块在内存造成单块读;
或由于DML操作相对频繁,可能读到的数据需要与undo构造一致性读数据块的几率也较高,此时查看等待事件都是采用单块读方式,从表面现象来看刚开始同步时同步速度很快,越到后面越慢,最终无法快速完成或出现快照过旧问题。当然,在DML频繁的表上创建Trigger,会源表的DML性能造成影响,需要提前评估。对于一些小表的同步,仍然建议使用Prebuilt
MV,原因简单方便,此思想也适合于其他数据库。
本示例实现目标:
将源端
user01.user_table 表数据迁移至目标端 user02.user_table,并实现目标端数据与源端数据定期实时的数据一致性同步。若进行业务迁移,对业务影响控制在1分钟时间内并,选择合适的时间点切换,基本可以做到重启应用程序所需时间,换句话说就是对业务的影响取决于应用程序的重启时间。
数据库源 端:业务数据库1
数据库目标端:业务数据库2
源 端 user01.user_table表:
表大小:60GB+,记录数:4.8亿+,每天DML量:200W左右,晚上22点后至第二天早上8点DML量较少,此时间段为空闲时间段,可在此时间段做初始化操作;
采用user_id做hash分区,分区数:16,主键字段:user_id+serviceid,唯一索引字段:uin+serviceid;
目标端 user02.user_table表:
采用uin做hash分区,分区数:64,主键字段:uin+serviceid,唯一索引字段:user_id+serviceid(目前生产库上依据业务情况,已不用该索引查询)。
限制:
1、源表需要有主键或者非空的唯一约束;
2、在同步期间,不支持对源表做DDL操作(注: 可以改进代码达成支持DDL的效果);
3、DML频繁的表不适合,可能会导致增量跟不上(注:没标准,取决于数据库性能)。
实施步骤简要说明:
注:红色字体为目标端操作,绿色字体为源端操作。
1、创建目标表:user02.user_table,并打开行移动(alter table
user02.user_table enable row
movement;),源端会对uin进行update,暂且不创建索引,待全量同步完成后创建索引,以免影响全量同步速度;
2、创建同步状态表(user02.rep_table_flag),用于记录同步存储过程运行状态;
3、创建错误日志表(user02.os_err_info)及序列(user02.seq_os_err_info
注:如果计划该表是和业务系统共用,请建成范围分区表);
4、创建同步日志表(user01.user_table_rep_sync_log)及序列(user01.seq_user_table_rep_sync_log),用于记录源表的DML操作信息;
5、创建触发器(user01.trigger_user_table_rep),将捕获的到信息插入日志同步表(注:创建触发器在改业务表空闲时间段进行,减少DML日志量生产,并对业务影响较小,并且一定要在全量同步前创建);
6、创建目标库连接源数据库的dblink(TO_XXXXX.LOCALDOMAIN),并且对同步同步表user01.user_table_rep_sync_log有DML权限;
7、创建增量数据同步存储过程(user02.proc_user_table_repl);
8、全量同步源表数据至目标表,如:exp/imp、impdp无落地迁移、存储过程拉数据等均可,本示例采用存储过程拉数据;
9、为目标表创建主键及相关索引;
10、以上完成后在目标库执行数据同步存储过程(user02.proc_user_table_repl),可建job定时刷新;
11、监控同步日志表(user01.user_table_rep_sync_log),观察需要同步的数据量。
如果做业务系统割接则需要业务程序配合,监控需要同步的数据量在刷新间隔时间期间最少时,停止定时刷新job,关闭旧业务程序,在目标库手动执行同步刷新直至同步日志表无新记录生成,启动新业务程序,以达到对业务系统影响最小的效果。