ITPub博客

首页 > 数据库 > Oracle > 创建Materialized view log时是否使用sequence clause的差别

创建Materialized view log时是否使用sequence clause的差别

原创 Oracle 作者:oliseh 时间:2015-09-11 15:47:00 0 删除 编辑

创建物化视图日志的时候有一个选项是sequence,对于sequence的作用,Data Warehousing guide里有一段描述:

Oracle recommends that the keyword SEQUENCE  be included in your materialized 
view log statement unless you are sure that you will never perform a mixed DML 
operation (a combination of  INSERT ,  UPDATE , or  DELETE  operations on multiple 
tables


在利用物化视图日志对物化视图进行的一次增量刷新的过程中,如果物化视图基于多个master table而建立,且至少两个master table的MV log日志都有更新记录,那么这些mlog$_开头的日志表里就必须包含sequence$$字段,也就是说在MV log定义的时候要使用sequence选项,这样才能使物化视图能够正常刷新。
理解这句话的关键在于什么是"一次增量刷新",增量刷新有两种:"refresh fast on demand"和"refresh fast on commit";对于"refresh fast on demand"一次增量刷新就是指执行一次dbms_mview.refresh将MV log里留存的内容读取出来更新到MV;对于"refresh fast on commit"一次增量更新就是在一个Transaction commit后将MV log里保存的对于master table的更改同步到MV。不管哪种方式当一次增量刷新的过程中发现两个以上的master table有了更改,就必须要求master table的MV log具有sequence$$字段,否则更新将无法同步到MV


/////////////////////////
// Create MV log的时候定义了sequence
/////////////////////////

###1、refresh on demand的情况
sqlplus hr/oracle
create table t0910_f1(stuid number constraint pk_stuid primary key,stuname varchar2(10)) tablespace ts0727;
create table t0910_d1(score number,stuid number constraint fk_stuid references t0910_f1(stuid),subject varchar2(10)) tablespace ts0727;
insert into t0910_f1 values(1,'stua');
insert into t0910_f1 values(2,'stub');
insert into t0910_f1 values(3,'stuc');


insert into t0910_d1 values(50,1,'maths');
insert into t0910_d1 values(60,2,'language');
insert into t0910_d1 values(80,1,'language');
insert into t0910_d1 values(40,2,'maths');
insert into t0910_d1 values(30,3,'language');
insert into t0910_d1 values(60,3,'maths');
commit;


create materialized view log on t0910_f1 tablespace ts0727 with rowid,sequence (stuid,stuname) including new values;
create materialized view log on t0910_d1 tablespace ts0727 with rowid,sequence (score,stuid,subject) including new values;

SQL> desc mlog$_t0910_f1;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 STUID                                              NUMBER
 STUNAME                                            VARCHAR2(10)
 M_ROW$$                                            VARCHAR2(255)
 SEQUENCE$$                                         NUMBER                <----创建了MV log时使用了sequence后就有了SEQUENCE$$列
 SNAPTIME$$                                         DATE
 DMLTYPE$$                                          VARCHAR2(1)
 OLD_NEW$$                                          VARCHAR2(1)
 CHANGE_VECTOR$$                                    RAW(255)
 XID$$                                              NUMBER


create materialized view mv0910_1 build immediate refresh fast with rowid enable query rewrite as select f.stuname,sum(score),avg(score),count(score),count(*) from t0910_d1 d,t0910_f1 f where f.stuid=d.stuid group by f.stuname;


update t0910_f1 set stuname='stuaa' where stuname='stua';
commit;


update t0910_d1 set score=score-10 where stuid=1;
commit;


SQL> select count(*) from mlog$_t0910_f1;


  COUNT(*)
----------
         2


SQL> select count(*) from mlog$_t0910_d1;


  COUNT(*)
----------
         4


exec dbms_mview.refresh('hr.mv0910_1');


SQL> select * from hr.mv0910_1;


STUNAME    SUM(SCORE) AVG(SCORE) COUNT(SCORE)   COUNT(*)
---------- ---------- ---------- ------------ ----------
stub              100         50            2          2
stuc               90         45            2          2
stuaa             110         55            2          2


###2、refresh on commit的场景
。。。略去,结果同上,MV能够正常更新


/////////////////////////
// Create MV log的时候未定义sequence
/////////////////////////

###1、refresh on demand的情况
drop table t0910_d1;
drop table t0910_f1;
drop materialized view mv0910_1;


create table t0910_f1(stuid number constraint pk_stuid primary key,stuname varchar2(10)) tablespace ts0727;
create table t0910_d1(score number,stuid number constraint fk_stuid references t0910_f1(stuid),subject varchar2(10)) tablespace ts0727;
insert into t0910_f1 values(1,'stua');
insert into t0910_f1 values(2,'stub');
insert into t0910_f1 values(3,'stuc');


insert into t0910_d1 values(50,1,'maths');
insert into t0910_d1 values(60,2,'language');
insert into t0910_d1 values(80,1,'language');
insert into t0910_d1 values(40,2,'maths');
insert into t0910_d1 values(30,3,'language');
insert into t0910_d1 values(60,3,'maths');
commit;


create materialized view log on t0910_f1 tablespace ts0727 with rowid (stuid,stuname) including new values;
create materialized view log on t0910_d1 tablespace ts0727 with rowid (score,stuid,subject) including new values;


create materialized view mv0910_1 build immediate refresh fast with rowid enable query rewrite as select f.stuname,sum(score),avg(score),count(score),count(*) from t0910_d1 d,t0910_f1 f where f.stuid=d.stuid group by f.stuname;




SQL> select * from mv0910_1;


STUNAME    SUM(SCORE) AVG(SCORE) COUNT(SCORE)   COUNT(*)
---------- ---------- ---------- ------------ ----------
stub              100         50            2          2
stua              130         65            2          2
stuc               90         45            2          2


update t0910_f1 set stuname='stuaa' where stuname='stua';   <---这两个update尽管在不同的transaction里提交,也会报"ORA-32316"错误,因为是refresh on demand
commit;


update t0910_d1 set score=score-10 where stuid=1;
commit;


SQL> select count(*) from mlog$_t0910_f1;


  COUNT(*)
----------
         2


SQL> select count(*) from mlog$_t0910_d1;


  COUNT(*)
----------
         4


SQL> exec dbms_mview.refresh('hr.mv0910_1');
BEGIN dbms_mview.refresh('hr.mv0910_1'); END;


*
ERROR at line 1:
ORA-32316: REFRESH FAST of "HR"."MV0910_1" unsupported after mixed DML
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2558
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2771
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2740
ORA-06512: at line 1


SQL> select * from hr.mv0910_1;


STUNAME    SUM(SCORE) AVG(SCORE) COUNT(SCORE)   COUNT(*)
---------- ---------- ---------- ------------ ----------
stub              100         50            2          2
stua              130         65            2          2
stuc               90         45            2          2


SQL> select count(*) from mlog$_t0910_f1;


  COUNT(*)
----------
         2


SQL> select count(*) from mlog$_t0910_d1;


  COUNT(*)
----------
         4


exec dbms_mview.refresh('hr.mv0910_1');


SQL> col msgtxt format a50
SQL> col mvname format a8
SQL> col capability_name format a29
SQL> col mvowner format a5
SQL> set linesize 150 pagesize 100


exec dbms_mview.explain_mview('hr.mv0910_1','chh1');           <----使用explain_mview结果明确指出因mv log没有sequence,而无法支持multi-table下除insert外的其它DML语句,仅支持在one-table下的ANY DML更新以及对于multi-tables的Insert语句


select mvowner,mvname, capability_name,possible,msgtxt from hr.mv_capabilities_table where possible='N'


MVOWN MVNAME   CAPABILITY_NAME      P MSGTXT
----- -------- -------------------- - --------------------------------------------------
HR    MV0910_1 PCT                  N
HR    MV0910_1 PCT_TABLE            N relation is not a partitioned table
HR    MV0910_1 PCT_TABLE            N relation is not a partitioned table
HR    MV0910_1 REFRESH_FAST_AFTER_A N mv log does not have sequence #         <--- MV log上没有sequence
               NY_DML
               
HR    MV0910_1 REFRESH_FAST_AFTER_A N mv log does not have sequence #         <--- MV log上没有sequence
               NY_DML


HR    MV0910_1 REFRESH_FAST_PCT     N PCT is not possible on any of the detail tables in
                                       the materialized view
HR    MV0910_1 REWRITE_PCT          N general rewrite is not possible or PCT is not poss
                                      ible on any of the detail tables


HR    MV0910_1 PCT_TABLE_REWRITE    N relation is not a partitioned table
HR    MV0910_1 PCT_TABLE_REWRITE    N relation is not a partitioned table

###2、refresh on commit的情况
drop table t0910_d1;
drop table t0910_f1;
drop materialized view mv0910_1;

create table t0910_f1(stuid number constraint pk_stuid primary key,stuname varchar2(10)) tablespace ts0727;
create table t0910_d1(score number,stuid number constraint fk_stuid references t0910_f1(stuid),subject varchar2(10)) tablespace ts0727;
insert into t0910_f1 values(1,'stua');
insert into t0910_f1 values(2,'stub');
insert into t0910_f1 values(3,'stuc');

insert into t0910_d1 values(50,1,'maths');
insert into t0910_d1 values(60,2,'language');
insert into t0910_d1 values(80,1,'language');
insert into t0910_d1 values(40,2,'maths');
insert into t0910_d1 values(30,3,'language');
insert into t0910_d1 values(60,3,'maths');
commit;


create materialized view log on t0910_f1 tablespace ts0727 with rowid (stuid,stuname) including new values;
create materialized view log on t0910_d1 tablespace ts0727 with rowid (score,stuid,subject) including new values;


create materialized view mv0910_1 build immediate refresh fast on commit with rowid enable query rewrite as select f.stuname,sum(score),avg(score),count(score),count(*) from t0910_d1 d,t0910_f1 f where f.stuid=d.stuid group by f.stuname;




SQL> select * from mv0910_1;


STUNAME    SUM(SCORE) AVG(SCORE) COUNT(SCORE)   COUNT(*)
---------- ---------- ---------- ------------ ----------
stua              130         65            2          2
stub              100         50            2          2
stuc               90         45            2          2


update t0910_f1 set stuname='stuaa' where stuname='stua';   <---当这两个update在不同的transaction里提交,一切正常
commit;


update t0910_d1 set score=score-10 where stuid=1;
commit;


SQL> select count(*) from mlog$_t0910_f1;


  COUNT(*)
----------
         0


SQL> select count(*) from mlog$_t0910_d1;


  COUNT(*)
----------
         0


SQL> select * from hr.mv0910_1;


STUNAME    SUM(SCORE) AVG(SCORE) COUNT(SCORE)   COUNT(*)
---------- ---------- ---------- ------------ ----------
stub              100         50            2          2
stuc               90         45            2          2
stuaa             110         55            2          2


update t0910_f1 set stuname='stua' where stuname='stuaa';   <---当这两个update在同一个transaction里提交,就有问题了


update t0910_d1 set score=score-10 where stuid=1;


SQL> select count(*) from mlog$_t0910_f1;


  COUNT(*)
----------
         2


SQL> select count(*) from mlog$_t0910_d1;


  COUNT(*)
----------
         4


SQL> commit;          <---虽然提交时没有报错


Commit complete.


SQL> select count(*) from mlog$_t0910_f1;   <---MV log表的内容已经消失了


  COUNT(*)
----------
         0


SQL> select count(*) from mlog$_t0910_d1;   <---MV log表的内容已经消失了


  COUNT(*)
----------
         0


SQL> select * from mv0910_1;            <---但是MV本身却没有更新


STUNAME    SUM(SCORE) AVG(SCORE) COUNT(SCORE)   COUNT(*)
---------- ---------- ---------- ------------ ----------
stuaa             110         55            2          2
stub              100         50            2          2
stuc               90         45            2          2


***alert.log里可以看到一行提示表名本次增量刷新没有成功,因为MV log已经被清除,只能使用complete refresh解决
Fri Sep 11 15:29:39 2015
Following on-commit snapshots not refreshed :
NEWUSER.MV0910_1 

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

请登录后发表评论 登录
全部评论
不仅仅专注Oracle database技术, member of SHOUG

注册时间:2014-04-06

  • 博文量
    128
  • 访问量
    1641818