11.2中物化视图日志可以指定COMMIT SCN,这时物化视图刷新就不需要时间戳了,这篇简单描述Oracle是如何实现通过COMMIT SCN来进行刷新的。


这一篇继续分析Oracle是如何实现快速刷新的。


从上一篇得到的TRACE不难发现,物化视图快速刷新由原来的3条SQL,变成了现在的2条。INSERT和UPDATE语句被合并为一个MERGE语句。


首先来看DELETE语句:


DELETE FROM "TEST"."MV_T" SNAP$


WHERE "ID" IN


(


SELECT DISTINCT LOG$."ID"


FROM


(


 SELECT MLOG$."ID"


 FROM "TEST"."MLOG$_T" MLOG$ ,  ALL_SUMMAP MAP$


 WHERE MLOG$.XID$$ = MAP$.XID


 AND MAP$.COMMIT_SCN > :1


 AND MAP$.COMMIT_SCN <= :2


 AND ("DMLTYPE$$" != 'I')


) LOG$


WHERE (LOG$."ID") NOT IN


(


 SELECT MAS_TAB$."ID"


 FROM "T" "MAS_TAB$"


 WHERE LOG$."ID" = MAS_TAB$."ID"


)


)


/* MV_REFRESH (MRG) */


MERGE INTO "TEST"."MV_T" "SNA$"


USING


(


SELECT CURRENT$."ID",CURRENT$."NAME",CURRENT$."AGE"


FROM


(


 SELECT "T"."ID" "ID","T"."NAME" "NAME","T"."AGE" "AGE"


 FROM "T" "T"


) CURRENT$,


(


 SELECT DISTINCT MLOG$."ID"


 FROM "TEST"."MLOG$_T" MLOG$,  ALL_SUMMAP MAP$


 WHERE MLOG$.XID$$ = MAP$.XID


 AND MAP$.COMMIT_SCN > :1


 AND MAP$.COMMIT_SCN <= :2


 AND ("DMLTYPE$$" != 'D')


) LOG$


WHERE CURRENT$."ID" = LOG$."ID"


)"AV$"


ON ("SNA$"."ID" = "AV$"."ID")


WHEN MATCHED THEN UPDATE


SET "SNA$"."ID" = "AV$"."ID","SNA$"."NAME" = "AV$"."NAME","SNA$"."AGE" = "AV$"."AGE"


WHEN NOT MATCHED THEN INSERT


(SNA$."ID",SNA$."NAME",SNA$."AGE")


VALUES (AV$."ID",AV$."NAME",AV$."AGE")


虽然是3条语句变成了2条,但是从SQL的目的看,和时间戳的物化视图刷新并没有本质的不同。由于不再使用时间戳而改为利用COMMIT SCN,因此Oracle引入了一个辅助表ALL_SUMMAP,通过ALL_SUMMAP将XID转化为对应的SCN。


下面简单看看ALL_SUMMAP的特性:


SQL> SELECT * FROM ALL_SUMMAP;


            XID       COMMIT_SCN


---------------- ----------------


2533498128696031    1112622614013


SQL> SELECT * FROM MLOG$_T;


未选定行


SQL> UPDATE T SET NAME = 'TEST' WHERE ID = 10;


已更新1行。


SQL> COMMIT;


提交完成。


SQL> SELECT * FROM MLOG$_T;


             ID D O CHANGE_VECTOR$$                           XID$$


---------------- - - ------------------------------ ----------------


             10 U U 04                             2814848551361701


SQL> SELECT * FROM ALL_SUMMAP;


            XID       COMMIT_SCN


---------------- ----------------


2814848551361701    1112622655597


2533498128696031    1112622614013


SQL> DELETE T WHERE ID = 10;


已删除1行。


SQL> COMMIT;


提交完成。


SQL> SELECT * FROM ALL_SUMMAP;


            XID       COMMIT_SCN


---------------- ----------------


2814848551361701    1112622655597


1970586829980189    1112622655626


2533498128696031    1112622614013


SQL> SELECT * FROM MLOG$_T;


             ID D O CHANGE_VECTOR$$                           XID$$


---------------- - - ------------------------------ ----------------


             10 U U 04                             2814848551361701


             10 D O 00                             1970586829980189


SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')


PL/SQL过程已成功完成。


SQL> SELECT * FROM ALL_SUMMAP;


            XID       COMMIT_SCN


---------------- ----------------


2814848551361701    1112622655597


1970586829980189    1112622655626


2533498128696031    1112622614013


SQL> CREATE TABLE T_TEST (ID NUMBER PRIMARY KEY);


表已创建。


SQL> CREATE MATERIALIZED VIEW LOG ON T_TEST WITH COMMIT SCN;


实体化视图日志已创建。


SQL> INSERT INTO T_TEST VALUES (1);


已创建1行。


SQL> SELECT * FROM MLOG$_T_TEST;


             ID D O CHANGE_VECTOR$$                           XID$$


---------------- - - ------------------------------ ----------------


              1 I N FE                             2815041824890019


SQL> SELECT * FROM ALL_SUMMAP;


            XID       COMMIT_SCN


---------------- ----------------


2814848551361701    1112622655597


1970586829980189    1112622655626


2533498128696031    1112622614013


SQL> CREATE MATERIALIZED VIEW MV_T_TEST


 2  REFRESH FAST


 3  AS SELECT *    


 4  FROM T_TEST;


实体化视图已创建。


SQL> SELECT * FROM ALL_SUMMAP;


            XID       COMMIT_SCN


---------------- ----------------


2814848551361701    1112622655597


1970586829980189    1112622655626


2815041824890019    1112622655813


2533498128696031    1112622614013


从上面的一系列的测试可以看到,ALL_SUMMAP中的记录对应的是物化视图需要刷新的每个事务。如果没有建立物化视图,只是包含物化视图日志,这时基表的修改不会导致ALL_SUMMAP中新增记录。而每个物化视图需要刷新的每个记录都会在这个表增加一条记录。


因此物化视图刷新的时候只需要刷新SCN大于上次刷新的SCN的修改,就可以确保刷新到最新的状态。



oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html