11.2中物化视图日志可以指定COMMIT SCN,这时物化视图刷新就不需要时间戳了,这篇简单描述Oracle是如何实现通过COMMIT SCN来进行刷新的。
建立一个测试环境:
SQL> SELECT * FROM V$VERSION;
BANNER
--------------------------------------------------------------------------------
Oracle Database11gEnterprise Edition Release11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> CREATE TABLE T
2 (ID NUMBER PRIMARY KEY,
3 NAME VARCHAR2(30),
4 AGE NUMBER(3));
表已创建。
SQL> INSERT INTO T
2 SELECT ROWNUM, TNAME, ROWNUM
3 FROM TAB;
已创建18行。
SQL> CREATE MATERIALIZED VIEW LOG ON T
2 WITH COMMIT SCN;
实体化视图日志已创建。
SQL> CREATE MATERIALIZED VIEW MV_T REFRESH FAST
2 AS SELECT * FROM T;
实体化视图已创建。
对物化视图基表进行修改:
SQL> INSERT INTO T
2 VALUES (20, 'TEST', 100);
已创建1行。
SQL> UPDATE T
2 SET NAME = 'TEST UPDATE'
3 WHERE ID = 1;
已更新1行。
SQL> DELETE T
2 WHERE ID = 2;
已删除1行。
SQL> COMMIT;
提交完成。
SQL>COLCHANGE_VECTOR$$ FORMAT A30
SQL> SET NUMW 16
SQL> SELECT * FROM MLOG$_T;
ID D O CHANGE_VECTOR$$ XID$$
---------------- - - ------------------------------ ----------------
20 I N FE 2533498128696031
1 U U 04 2533498128696031
2 D O 00 2533498128696031
可以看到物化视图日志中记录了INSERT、UPDATE和DELETE操作,由于指定了COMMIT SCN,物化视图日志中多出了XID$$列,而缺少了SNAPTIME$$列。
SQL> CREATE TABLE T_TIMESTAMP (ID NUMBER PRIMARY KEY);
表已创建。
SQL> CREATE MATERIALIZED VIEW LOG ON T_TIMESTAMP;
实体化视图日志已创建。
SQL> INSERT INTO T_TIMESTAMP VALUES (1);
已创建1行。
SQL> SELECT * FROM MLOG$_T_TIMESTAMP;
ID SNAPTIME$$ D O CHANGE_VECTOR$$ XID$$
---------------- -------------- - - ------------------------------ ----------------
1 01-1月-00 I N FE 2814912975871092
可以看到,即使不指定WITH COMMIT SCN,11.2的物化视图日志也会包含XID$$列,估计是为了实现统一的接口。
下面对刷新过程进行TRACE,看看Oracle是如何实现刷新的:
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
会话已更改。
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL过程已成功完成。
SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';
会话已更改。
SQL> SELECT SPID
2 FROM V$PROCESS P, V$SESSION S
3 WHERE P.ADDR = S.PADDR
4 AND SID IN
5 (SELECT SID
6 FROM V$MYSTAT
7 WHERE ROWNUM = 1);
SPID
------------------------
9862
检查对应的日志:
Trace file /data/oracle/diag/rdbms/test112/test112/trace/test112_ora_9862.trc
Oracle Database11gEnterprise Edition Release11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /data/oracle/product/11.2
System name: Linux
Node name: bjtest
Release: 2.6.18-8.el5xen
Version: #1 SMP Tue Jun 5 23:53:34 EDT 2007
Machine: x86_64
Instance name: test112
Redo thread mounted by this instance: 1
Oracle process number: 25
Unix process pid: 9862, image: oracle@bjtest (TNS V1-V3)
*** 2010-01-20 02:29:42.045
*** SESSION ID:(146.5127) 2010-01-20 02:29:42.045
*** CLIENT ID:() 2010-01-20 02:29:42.045
*** SERVICE NAME:(SYS$USERS) 2010-01-20 02:29:42.045
*** MODULE NAME:(SQL*Plus) 2010-01-20 02:29:42.045
*** ACTION NAME:() 2010-01-20 02:29:42.045
WAIT #3: nam='SQL*Net message to client' ela= 5 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1263925782044841
*** 2010-01-20 02:29:52.082
WAIT #3: nam='SQL*Net message from client' ela= 10037338 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1263925792082882
CLOSE #3:c=0,e=36,dep=0,type=1,tim=1263925792083083
=====================
PARSING IN CURSOR #2 len=40 dep=0 uid=85 ct=47 lid=85 tim=1263925792083357 hv=227083342 ad='1f3d5d940' sqlid='7z7aqjn6sk12f'
BEGIN DBMS_MVIEW.REFRESH('MV_T'); END;
END OF STMT
PARSE #2:c=0,e=184,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=0,tim=1263925792083352
=====================
PARSING IN CURSOR #8 len=11 dep=1 uid=0 ct=44 lid=0 tim=1263925792084131 hv=1180858989 ad='0' sqlid='87rnsy1364ymd'
COMMIT WORK
END OF STMT
PARSE #8:c=0,e=36,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=0,plh=0,tim=1263925792084126
XCTEND rlbk=0, rd_only=0, tim=1263925792084276
=====================
.
.
.
=====================
PARSING IN CURSOR #12 len=378 dep=1 uid=85 ct=7 lid=85 tim=1263925792302844 hv=4055642071 ad='1ef8d5650' sqlid='6rvarb7svsbyr'
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"))
END OF STMT
PARSE #12:c=0,e=600,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=1,plh=0,tim=1263925792302839
=====================
.
.
.
BINDS #12:
Bind#0
acdty=02 mxl=22(08) mxlc=00 mal=00 scl=00 pre=00
acflg=10 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=7fffb51b5fa8 bln=22 avl=08 flg=09
value=1112622613804
Bind#1
acdty=02 mxl=22(08) mxlc=00 mal=00 scl=00 pre=00
acflg=10 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=7fffb51b5f90 bln=22 avl=08 flg=09
value=1112622614232
WAIT #12: nam='asynch descriptor resize' ela= 5 outstanding #aio=0 current aio limit=180 new aio limit=245 obj#=-1 tim=1263925792381973
WAIT #12: nam='asynch descriptor resize' ela= 3 outstanding #aio=0 current aio limit=245 new aio limit=180 obj#=-1 tim=1263925792382401
EXEC #12:c=32002,e=79680,p=0,cr=48,cu=3,mis=1,r=1,dep=1,og=1,plh=3947379916,tim=1263925792382655
STAT #12 id=1 cnt=0 pid=0 pos=1 bj=0 p='DELETE MV_T (cr=13 pr=0 pw=0 time=0 us)'
STAT #12 id=2 cnt=1 pid=1 pos=1 bj=0 p='NESTED LOOPS (cr=13 pr=0 pw=0 time=0 us cost=9 size=26 card=1)'
STAT #12 id=3 cnt=1 pid=2 pos=1 bj=0 p='VIEW VW_NSO_1 (cr=12 pr=0 pw=0 time=0 us cost=8 size=26 card=2)'
STAT #12 id=4 cnt=1 pid=3 pos=1 bj=0 p='SORT UNIQUE (cr=12 pr=0 pw=0 time=0 us)'
STAT #12 id=5 cnt=1 pid=4 pos=1 bj=0 p='FILTER (cr=12 pr=0 pw=0 time=0 us)'
STAT #12 id=6 cnt=2 pid=5 pos=1 bj=0 p='FILTER (cr=10 pr=0 pw=0 time=6 us)'
STAT #12 id=7 cnt=2 pid=6 pos=1 bj=0 p='HASH JOIN (cr=10 pr=0 pw=0 time=0 us cost=7 size=108 card=2)'
STAT #12 id=8 cnt=1 pid=7 pos=1 bj=636 p='TABLE ACCESS FULL SNAP_XCMT$ (cr=3 pr=0 pw=0 time=0 us cost=2 size=26 card=1)'
STAT #12 id=9 cnt=2 pid=7 pos=2 bj=84200 p='TABLE ACCESS FULL MLOG$_T (cr=7 pr=0 pw=0 time=0 us cost=4 size=56 card=2)'
STAT #12 id=10 cnt=1 pid=5 pos=2 bj=84199 p='INDEX UNIQUE SCAN SYS_C0011157 (cr=2 pr=0 pw=0 time=0 us cost=1 size=13 card=1)'
STAT #12 id=11 cnt=1 pid=2 pos=2 bj=84203 p='INDEX UNIQUE SCAN SYS_C0011158 (cr=1 pr=0 pw=0 time=0 us cost=0 size=13 card=1)'
=====================
.
.
.
=====================
PARSING IN CURSOR #12 len=690 dep=1 uid=85 ct=189 lid=85 tim=1263925792384809 hv=766335958 ad='1f3c8d7f8' sqlid='7x4b9jnquuqyq'
/* 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")
END OF STMT
PARSE #12:c=0,e=796,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=1,plh=0,tim=1263925792384804
=====================
.
.
.
BINDS #12:
Bind#0
acdty=02 mxl=22(08) mxlc=00 mal=00 scl=00 pre=00
acflg=10 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=7fffb51b5f38 bln=22 avl=08 flg=09
value=1112622613804
Bind#1
acdty=02 mxl=22(08) mxlc=00 mal=00 scl=00 pre=00
acflg=10 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=7fffb51b5f20 bln=22 avl=08 flg=09
value=1112622614232
WAIT #12: nam='asynch descriptor resize' ela= 6 outstanding #aio=0 current aio limit=180 new aio limit=245 obj#=-1 tim=1263925792433371
WAIT #12: nam='asynch descriptor resize' ela= 4 outstanding #aio=0 current aio limit=245 new aio limit=180 obj#=-1 tim=1263925792433722
EXEC #12:c=40002,e=59289,p=0,cr=83,cu=27,mis=1,r=2,dep=1,og=1,plh=670631188,tim=1263925792444269
STAT #12 id=1 cnt=0 pid=0 pos=1 bj=0 p='MERGE MV_T (cr=22 pr=0 pw=0 time=0 us)'
STAT #12 id=2 cnt=2 pid=1 pos=1 bj=0 p='VIEW (cr=17 pr=0 pw=0 time=101 us)'
STAT #12 id=3 cnt=2 pid=2 pos=1 bj=0 p='NESTED LOOPS OUTER (cr=17 pr=0 pw=0 time=96 us cost=11 size=222 card=2)'
STAT #12 id=4 cnt=2 pid=3 pos=1 bj=0 p='NESTED LOOPS (cr=14 pr=0 pw=0 time=53 us cost=10 size=112 card=2)'
STAT #12 id=5 cnt=2 pid=4 pos=1 bj=0 p='VIEW (cr=10 pr=0 pw=0 time=9 us cost=8 size=26 card=2)'
STAT #12 id=6 cnt=2 pid=5 pos=1 bj=0 p='SORT UNIQUE (cr=10 pr=0 pw=0 time=3 us cost=8 size=108 card=2)'
STAT #12 id=7 cnt=2 pid=6 pos=1 bj=0 p='FILTER (cr=10 pr=0 pw=0 time=18 us)'
STAT #12 id=8 cnt=2 pid=7 pos=1 bj=0 p='HASH JOIN (cr=10 pr=0 pw=0 time=14 us cost=7 size=108 card=2)'
STAT #12 id=9 cnt=1 pid=8 pos=1 bj=636 p='TABLE ACCESS FULL SNAP_XCMT$ (cr=3 pr=0 pw=0 time=0 us cost=2 size=26 card=1)'
STAT #12 id=10 cnt=2 pid=8 pos=2 bj=84200 p='TABLE ACCESS FULL MLOG$_T (cr=7 pr=0 pw=0 time=3 us cost=4 size=56 card=2)'
STAT #12 id=11 cnt=2 pid=4 pos=2 bj=84198 p='TABLE ACCESS BY INDEX ROWID T (cr=4 pr=0 pw=0 time=0 us cost=1 size=43 card=1)'
STAT #12 id=12 cnt=2 pid=11 pos=1 bj=84199 p='INDEX UNIQUE SCAN SYS_C0011157 (cr=2 pr=0 pw=0 time=0 us cost=0 size=0 card=1)'
STAT #12 id=13 cnt=1 pid=3 pos=2 bj=84202 p='MAT_VIEW ACCESS BY INDEX ROWID MV_T (cr=3 pr=0 pw=0 time=0 us cost=1 size=55 card=1)'
STAT #12 id=14 cnt=1 pid=13 pos=1 bj=84203 p='INDEX UNIQUE SCAN SYS_C0011158 (cr=2 pr=0 pw=0 time=0 us cost=0 size=0 card=1)'
CLOSE #12:c=0,e=18,dep=1,type=0,tim=1263925792444951
CLOSE #9:c=0,e=17,dep=1,type=0,tim=1263925792445202
=====================
根据上面的TRACE结果不难分析出Oracle是如何实现快速刷新的。
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html