我们采用Oracle的物化视图增量刷新机制定时将数据库A上的某个表的数据同步到另一个数据库B上。
我们常用的最简单的实现步骤是这样。首先在数据库A上确认该表有主键,然后建立在这个表上建立物化视图日志如“CREATE MATERIALIZED VIEW LOG ON T_tablename;”,再到数据库B上创建数据库链接和快速刷新的物化视图如“create materialized view mv_tablename refresh fast on demand start with sysdate next sysdate+1/288 as select * from T_tablename@dblink_name;”。
现在,数据库A上此表的主键约束因主键字段值重复而被disable了,在第三个数据库C上新建这个物化视图却失败,说:“ORA-12014: 表 'T_MV_TEST' 不包含主键约束条件”。如果将此表的主键增加字段并ENABLE后操作,又说:“ORA-23412: 主表的主键列已更改”。
但有一个奇怪的现象:在数据库B上我们也建立过物化视图,它却在此表的主键disable之后,还是正常运行。
(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1753779 )
我们介绍一下在数据库B上的创建物化视图的操作过程。
首先,介绍环境。
数据库A和数据库B的版本为Oracle 10.2.0.4 for linux x86 64bit。
在数据库A上同步的表的结构如下:
create table T_MV_TEST ( A DATE, B DATE, C DATE ); alter table T_MV_TEST add constraint PK_T_MV_TEST primary key (A,B);
这是一个测试表,很简单的3个字段。
接着,创建物化视图日志
在数据库A上创建这个表的物化视图日志,我们使用的创建方法是最简洁的,如下:
CREATE MATERIALIZED VIEW LOG ON T_MV_TEST;
这将在表T_MV_TEST上创建一个触发器和一个日志表MLOG$_T_MV_TEST。
它和CREATE MATERIALIZED VIEW LOG ON T_MV_TEST WITH PRIMARY KEY;的效果是一样的,是省略掉WITH PRIMARY KEY的操作。
但是这个日志表只能捕获到主键字段的删除和增加操作,如果非主键字段值发生改变,则不会同步过去。这是这个简易方法的局限性。
最后,创建物化视图
在数据库B上创建定时增量更新的物化视图,方法如下:
create materialized view t_mv_test refresh fast on demand start with sysdate next sysdate+1/288 as select * from t_mv_test@dblink_name;
这是增量更新机制的物化视图的最简单的创建方法,将每5分钟检查数据库A上此表的主键字段的删除和插入操作而将变化的记录同步到另一个数据库B中。
这个过程同样也省略掉了with primary key关键字,它也是默认值。
create materialized view t_mv_test refresh fast on demand start with sysdate next sysdate+1/288 with primary key --默认值 as select * from t_mv_test@dblink_name;
我们再分析一下物化视图的机制。
在数据库B中创建的物化视图对应的表是有主键的,其主键和数据库A上这个表的主键一致。因此在创建物化视图时,要检查数据库A上的表是不是也有主键,主键是不是启用的。
在数据库A上此表的主键disable之后,数据库B上该主键还是enable的。同步过程中,只要主库上的原主键字段值不重复,同步会照常运行。即使主键字段值因主键约束disable之后而重复,也不会因此同步到数据库B中的。
这种简易的增量同步的物化视图创建方法,只能同步记录的插入和删除及主键字段的修改操作,至于其他字段的修改操作无法同步,甚至修改的先后顺序也不能正确同步。
因此,我们需要一种更加规范的物化视图创建方法。
1、在物化视图日志创建时,这样操作:
CREATE MATERIALIZED VIEW LOG ON T_MV_TEST WITH SEQUENCE, ROWID (A,B,C) INCLUDING NEW VALUES;
使用rowid,sequence捕获数据变化情况。如果在数据库B上需要使用with primary key方式创建物化视图,那么这里需要将primary key的值也捕获到。
CREATE MATERIALIZED VIEW LOG ON T_MV_TEST WITH PRIMARY KEY,SEQUENCE, ROWID (C) INCLUDING NEW VALUES;
注意:加上including new values子句,是为了记录数据修改前的值。
2、在物化视图创建时,这样操作:
create materialized view t_mv_test refresh fast on demand start with sysdate next sysdate+1/288 with rowid as select * from t_mv_test@dblink_name;
这样,不管数据库A上的此表的主键如何变化,我一概不管。但是,有时必须要使用with primary key,例如跨库跨平台时。
物化视图对应的表上没有主键,如果需要索引可以另行添加。
最后小结一下,这个文档借这个小问题分析一下物化视图运行机制,整理出更符合生产运行的物化视图创建规范。
有一篇文档可以参考一下:http://www.skill-guru.com/blog/2010/01/03/understanding-materialized-view-in-oracle/ 这个文档有助于你理解Oracle的物化视图。
附录一份时文,提醒自己。
12月24日上午9时左右,江西贵溪滨江乡洪塘村合盘石童家村小组一面包车侧翻坠入水塘,事发时该7座面包车上载有17人,致11名儿童死亡。12月24日晚23时,江西贵溪市政府公布儿童伤亡名单,年龄最大的儿童为6岁,最小的仅4岁。据悉,校车司机就是幼儿园长彭春娥。其为节省成本,只能让十几个孩子挤在一辆车上。