这篇文章主要讨论如何通过修改物化视图日志来同步包含LOB列的UPDATE操作。
小议物化视图与基表数据不一致的消除(一):http://yangtingkun.itpub.net/post/468/326751
小议物化视图与基表数据不一致的消除(二):http://yangtingkun.itpub.net/post/468/327727
小议物化视图与基表数据不一致的消除(三):http://yangtingkun.itpub.net/post/468/490927
前面一篇文章描述了如何通过手工修改物化视图日志的方法UPDATE操作的同步。
一般来说,对于UPDATE操作,没有必要关心具体需要修改的列,但是对于9i环境下包含LOB对象的物化视图,在使用上一篇文章介绍的方法就存在问题了。
在9.2中,当表中包含LOB时,如果记录的LOB字段在基表和物化视图中是一致的,那么物化视图日志中添加记录的时候,注意不要将LOB列包含在修改矢量中,否则由于LOB存储信息很多,会降低物化视图刷新的性能。如果记录的LOB字段在基表和物化视图中是不一致的,那么在添加物化视图日志记录的时候,需要明确指定LOB列被修改,否则物化视图的刷新不会同步LOB列。
看一个简单的例子,基表和物化视图查询结果如下:
SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production
SQL> SELECT * FROM T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 UPDATE It has been updated.
2 B 1234
3 C TEST
SQL> SELECT * FROM MV_T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 A ABCDEFG
2 B 1234
3 C TEST
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
SQL> SELECT * FROM MV_T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 A ABCDEFG
2 B 1234
3 C TEST
由于LOB列存在不同步的现象,如果还像上一篇文章中给出的方法,随意写入一个列修改值,将导致LOB列无法同步:
SQL> INSERT INTO MLOG$_T
2 VALUES (1, TO_DATE('4000-1-1', 'YYYY-MM-DD'), 'U', 'U', '04');
已创建 1 行。
SQL> UPDATE T SET NAME = 'D' WHERE ID = 3;
已更新 1 行。
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
SQL> SELECT * FROM T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 UPDATE It has been updated.
2 B 1234
3 D TEST
SQL> SELECT * FROM MV_T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 UPDATE ABCDEFG
2 B 1234
3 D TEST
手工人工添加MLOG$记录,使得ID为1的不一致的记录的NAME列得到同步,但是LOB列并没有同步。
因此在添加物化视图日志信息的时候必须指定LOB列,CHANGE_VECTOR$$的值是2的N次方,而这个N就是LOB列对应的列的顺序值。
但是需要注意的是,这个列的顺序值表示从DBA_TAB_COLUMNS中得到的,而是从SYS.COL$表中获取的:
SQL> SELECT POWER(2, INTCOL#)
2 FROM SYS.COL$
3 WHERE NAME = 'ADDRESS'
4 AND OBJ# =
5 (SELECT OBJECT_ID
6 FROM DBA_OBJECTS
7 WHERE WNER = USER
8 AND OBJECT_NAME = 'T');
POWER(2,COL#)
-------------
8
下面再次修改物化视图日志,并指定CHANGE_VECTOR$$为‘08’:
SQL> INSERT INTO MLOG$_T
2 VALUES (1, TO_DATE('4000-1-1', 'YYYY-MM-DD'), 'U', 'U', '08');
已创建 1 行。
SQL> UPDATE T SET NAME = 'E' WHERE ID = 3;
已更新 1 行。
SQL> SELECT * FROM T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 UPDATE It has been updated.
2 B 1234
3 E TEST
SQL> SELECT * FROM MV_T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 UPDATE ABCDEFG
2 B 1234
3 D TEST
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
SQL> SELECT * FROM MV_T;
ID NAME ADDRESS
---------- -------------------- ----------------------------------------
1 UPDATE It has been updated.
2 B 1234
3 E TEST
这次物化视图的LOB字段也得到同步。
关于物化视图日志字段的详细描述可以参考:http://yangtingkun.itpub.net/post/468/20498
关于物化视图是如何利用物化视图日志进行快速刷新的可以参考:http://yangtingkun.itpub.net/post/468/20584
物化视图字段级刷新的文章:
物化视图是否根据字段进行刷新(一):http://yangtingkun.itpub.net/post/468/201236
物化视图是否根据字段进行刷新(二):http://yangtingkun.itpub.net/post/468/201607
物化视图是否根据字段进行刷新(三):http://yangtingkun.itpub.net/post/468/203414
包含LOB的物化视图快速刷新:http://yangtingkun.itpub.net/post/468/493060
包含LOB的物化视图快速刷新(二):http://yangtingkun.itpub.net/post/468/493206
包含LOB的物化视图快速刷新(三):http://yangtingkun.itpub.net/post/468/493660
包含LOB的物化视图快速刷新(四):http://yangtingkun.itpub.net/post/468/493970
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8494287/viewspace-1394352/ ,如需转载,请注明出处,否则将追究法律责任。