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