ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 小议物化视图与基表数据不一致的消除(三)

小议物化视图与基表数据不一致的消除(三)

原创 Linux操作系统 作者:yangtingkun 时间:2009-08-31 23:57:31 0 删除 编辑

这篇文章主要讨论如何通过修改物化视图日志来同步UPDATE操作。

小议物化视图与基表数据不一致的消除(一):http://yangtingkun.itpub.net/post/468/326751

小议物化视图与基表数据不一致的消除(二):http://yangtingkun.itpub.net/post/468/327727

 

 

前面一篇文章描述了如何通过手工修改物化视图日志的方法来实现INSERTDELETE操作的同步。

也许有人认为有了INSERTDELETE的方法就不需要UPDATE的方法了,因为只需要在物化视图日志中插入一个DELETE的日志,然后在插入一个INSERT对应的日志信息,Oracle在刷新物化视图的时候,就会将需要UPDATE的记录先删除,然后重新插入。

但是,事情并不那么简单。物化视图的刷新并不仅仅依赖于物化视图日志中的内容,事实上,Oracle会根据物化视图和基表的差异来确定是否执行删除和插入的操作。

关于上面的描述可以参考:物化视图刷新并非完全根据物化视图日志记录:http://yangtingkun.itpub.net/post/468/486248

因此想要通过这种手工添加DELETEINSERT记录的方式来欺骗Oracle是行不通的。UPDATE操作就只能UPDATE的方式来解决。

虽然无法欺骗Oracle,录音DELETE + INSERT的方式来绕过UPDATE操作,但是在UPDATE操作需要更新的列上可以欺骗一下Oracle

Oracle处于性能的考虑,当表中不包含LOB列时,虽然物化视图日志明确的记录了哪些列需要被更新,但是Oracle并不会将更新细化到列级,而是表中所有的字段全部更新。这样的话,在处理UPDATE语句的时候就有了省事的办法。在物化视图日志表中手工编辑UPDATE记录的时候,可以在列标识的地方输入任意列,比如’02’。这样就可以实现物化视图和基表之前,同一条记录字段数据不同的同步操作。

SQL> exec dbms_mview.refresh('MV_T')

PL/SQL procedure successfully completed.

SQL> select * from t;

        ID NAME                                  AGE
---------- ------------------------------ ----------
         1 update                                 18
         2 b                                      26
         3 c                                      34
         4 d                                      40

SQL> select * from mv_t;

        ID NAME                                  AGE
---------- ------------------------------ ----------
         1 a                                      18
         2 b                                      26
         3 c                                      34
         4 d                                      40

现在基表和物化视图中ID1的记录是不同的。现在通过手工添加物化视图日志的方式来实现二者的同步:

SQL> desc mlog$_t               
 Name                                Null?    Type
 ----------------------------------- -------- ---------------
 ID                                           NUMBER
 SNAPTIME$$                                   DATE
 DMLTYPE$$                                    VARCHAR2(1)
 OLD_NEW$$                                    VARCHAR2(1)
 CHANGE_VECTOR$$                              RAW(255)

SQL> insert into mlog$_t values (1, to_date('4000-1-1', 'yyyy-mm-dd'), 'U', 'U', '01');

1 row created.

SQL> col change_vector$$ format a10
SQL> select * from mlog$_t;

        ID SNAPTIME$$     D O CHANGE_VEC
---------- -------------- - - ----------
         1 01-1
-00     U U 01

SQL> delete t where id = 4;

1 row deleted.

SQL> exec dbms_mview.refresh('MV_T')

PL/SQL procedure successfully completed.

SQL> select * from t;

        ID NAME                                  AGE
---------- ------------------------------ ----------
         1 update                                 18
         2 b                                      26
         3 c                                      34

SQL> select * from mv_t;

        ID NAME                                  AGE
---------- ------------------------------ ----------
         1 update                                 18
         2 b                                      26
         3 c                                      34

第一个字段表示发生变化的记录的ID

第二个是时间戳填入400011日,表示任何物化视图还没有对这个记录进行刷新。

第三个字段表示INSERT/UPDATE/DELETE

第四个字段表示新值(N/旧值(O/修改(U)。

最后一个字段表示修改列的矢量。由于UPDATE的时候会更新所有的非LOB列,因此这里并不需要对应到列上,比如这里插入的’01’实际上指向的是主键列。

关于物化视图日志字段的详细描述可以参考:http://yangtingkun.itpub.net/post/468/20498

关于物化视图是如何利用物化视图日志进行快速刷新的可以参考:http://yangtingkun.itpub.net/post/468/20584

修改MLOG后马上刷新并不会导致数据同步到物化视图,这是由于Oracle在快速刷新的时候发现基表自上次刷新完成后并未发生修改,因此根本没有去读取物化视图日志。

因此在上面的例子中对基表数据进行修改,使得物化视图刷新时,会读取手工添加的物化视图日志信息。

可以看到,通过手工修改物化视图日志的方式,使得Oracle的基表和物化视图日志实现了同步。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-613657/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1955
  • 访问量
    10405517