ITPub博客

首页 > 数据库 > Oracle > 物化视图日志结构与ORA-12034 Mview log younger than last refresh

物化视图日志结构与ORA-12034 Mview log younger than last refresh

Oracle 作者:兰在晨 时间:2016-02-28 15:20:07 0 删除 编辑
我们都知道,要创建快速刷新的物化视图,必须先在MASTER SITE端创建物化视图日志。这里介绍一下Mview Log 的结构与江门NGBOSS和之前来电三期中出现的ORA-12034 materialized view log younger than last refresh问题的原因。
我们先来看一下物化视图日志的结构含义和用途:物化视图日志的名称为MLOG$_后面跟基表的名称,如果表名的长度超过20位,则只取前20位,当截短后出现名称重复时,Oracle会自动在物化视图日志名称后面加上数字作为序号。
物化视图日志的建立可以指定为PRIMARY KEY、ROWID、和OBJECT ID几种类型,同时还可以指定SEQUENCE或明确指定列名。每种物化视图的结构都会有一些差异,不过它们都会包含以下列:
SNAPTIME$$:用于表示刷新时间。
DMLTYPE$$:用于表示DML操作类型,I表示INSERT,D表示DELETE,U表示UPDATE。
OLD_NEW$$:用于表示这个值是新值还是旧值。(N)表示新值,(O)表示旧值,U表示UPDATE操作。
CHANGE_VECTOR$$表示修改矢量,用来表示被修改的是哪个或哪几个字段。
物化视图日志默认为PRIMARY KEY,这种类型的物化视图日志中会包含主键列。
如果WITH后面跟了ROWID,则物化视图日志中会包含:
M_ROW$$:用来存储发生变化的记录的ROWID。
如果WITH后面跟了OBJECT ID,则物化视图日志中会包含:
SYS_NC_OID$:用来记录每个变化对象的OBJECT ID。
如果WITH后面跟了SEQUENCE,则物化视图日子中会包含:
SEQUENCE$$:给每个操作一个SEQUENCE号,从而保证刷新时按照顺序进行刷新。
如果WITH后面跟了一个或多个COLUMN名称,则物化视图日志中会包含这些列。
官方解释:
OBJECT ID:Specify OBJECT ID to indicate that the system-generated or user-defined object identifier of every modified row should be recorded in the materialized view log.
Restriction on OBJECT ID:You can specify OBJECT ID only when creating a log on an object table, and you cannot specify it for storage tables.
PRIMARY KEY:Specify PRIMARY KEY to indicate that the primary key of all rows changed should be recorded in the materialized view log.
ROWID:Specify ROWID to indicate that the rowid of all rows changed should be recorded in the materialized view log.
SEQUENCE:Specify SEQUENCE to indicate that a sequence value providing additional ordering information should be recorded in the materialized view log. Sequence numbers are necessary to support fast refresh after some update scenarios.[@more@]接下来我们看一下物化视图日志中的内容:
SQL> create table t_ty(pid number(2),pname varchar2(20),constraint t_ty_pk primary key(pid));
Table created.
SQL> create materialized view log on t_ty;
Materialized view log created.
SQL> desc mlog$_t_ty;
Name Null? Type
----------------------------------------- -------- ----------------------------
PID NUMBER(2)
SNAPTIME$$ DATE
DMLTYPE$$ VARCHAR2(1)
OLD_NEW$$ VARCHAR2(1)
CHANGE_VECTOR$$ RAW(255)
XID$$ NUMBER
这里默认是with primary key的物化视图日志,所以这里把主键字段pid加到物化视图日志中来,其他类型的物化视图日志会换成m_row$$、sys_nc_oid$字段。这里如果with中加入sequece或者指定一个或者多个字段,物化视图日志中就会包含SEQUENCE$$或者这些指定的列。下面看一下对表进行增、删、改后物化视图日志的内容:
SQL> insert into t_ty values(1,'ty');
1 row created.
SQL> insert into t_ty values(2,'snc');
1 row created.
SQL> update t_ty set pname='shsnc' where pid=2;
1 row updated.
SQL> update t_ty set pid=3 where pid=1;
1 row updated.
SQL> select pid,snaptime$$ ,dmltype$$,old_new$$,change_vector$$ from mlog$_t_ty;
PID SNAPTIME$$ DMLTYPE$$ OLD_NEW$$ CHANGE_VECTOR$$
----- ------------------------- -------------- ------------------ -----------------------
1 4000-01-01 00:00:00 I N FE
2 4000-01-01 00:00:00 I N FE
2 4000-01-01 00:00:00 U U 04
1 4000-01-01 00:00:00 D O 00
3 4000-01-01 00:00:00 I N FF
可以看到普通字段的更新会在日志中记录一条更新记录,如果是更新主键字段,则会先删除后插入一条新的记录。DMLTYPE$$、OLD_NEW$$这两个字段上面已经介绍过了,结合这里的日志内容可以一目了然。这里先介绍一下CHANGE_VECTOR$$字段,SNAPTIME$$字段在后面结合江门NGBOSS和之前来电三期中出现的ORA-12034 materialized view log younger than last refresh一块介绍。
CHANGE_VECTOR$$列是RAW类型,用于记录修改矢量,上面有四个值FE、04、00、FF。插入操作:插入操作用FE表示,如果表中列的个数大于8个,则在右边添加FF即FEFF,大于16个时,则在后面添加FFFF即FEFFFF。其实oracle是bit来计算列是个数,大于8个列时,十六进制的FF转换成二进制11111111已经无法表示全部的列的状态了。
删除操作:删除操作则用00表示,如果列的个数大于8个时则在后面添加00,以此类推。更新操作:更新操作分为主键列更新和非主键列的更新,如果是更新主键列,在日志中记录一条删除和一条插入,这时插入操作的FE换成FF,其他的生成方式没变。当更新某些列时,如果更新第一个列则02,即00000010,如果列的个数则在后面补充00,如果更新第二个列则为04,即00000100,即第几个列被更新则对应的二进制+1位由0变为1;比如第三和第五位更新则为00101000即十六进制的28。这里需要注意的是,如果表的列大于8个,则在右边补充两位,但在计算时右边两位为高位,比如第11和第17列被更新则为00000010 00001000 00000000即十六进制的000802。
下面结合江门NGBOSS和之前来电三期中出现的ORA-12034 materialized view log younger than last refresh介绍一下SNAPTIME$$字段,这个字段其实也是物化视图刷新最主要的依据。
先描述一下江门NGBOSS和之前来电三期的场景和出现的问题,来电三期是从管理节点分别向两个呼叫节点分发数据,物化视图每10秒中刷新一次。江门NGBOSS是需要融合计费建一张物化视图到CRM生产用户下,后面由于测试需要另外在源表上建一张物化视图到CRM的性能用户下,刷新时间均为1分钟。从场景和需求来看都是没有问题的,但是在创建物化视图时,却都出现了ORA-12034 materialized view log younger than last refresh。经过分析发现两次问题出现的场景有一个共同特点,那就是物化视图日志都是被重建过。了解物化视图刷新的原理就可以很清楚的知道问题的原因了,而物化视图刷新的机制恰恰是隐藏在物化视图的SNAPTIME$$字段中。下面结合例子,其实也就是上面的场景重现来介绍SNAPTIME$$字段。
创建物化视图基表并插入数据:
SQL> create table t_mv(pid number(4),pname varchar2(20),pdept varchar2(30), constraint pk_t_mv primary key(pid));
Table created.
SQL> declare
2 begin
3 for i in 1..99 loop
4 insert into t_mv values (i,'snc'||i,'咨询测试部'||i);
5 commit;
6 end loop;
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> create materialized view log on t_mv;
Materialized view log created.
模拟第一个物化视图端创建物化视图,创建一个1小时的物化视图:
SQL> create materialized view mv_1
2 refresh fast
3 start with sysdate
4 next sysdate + 1/24 /*1h*/
5 with primary key
6 as
7 select * from t_mv;
Materialized view created.
SQL> insert into t_mv values (21,'shsnc','咨询');
1 row created.
这里看一下SNAPTIME$$字段
SQL> select snaptime$$ from mlog$_t_mv;
SNAPTIME$$
-------------------
4000-01-01 00:00:00
创建第二个物化视图
SQL> create materialized view mv_2
2 refresh fast
3 start with sysdate
4 next sysdate + 1/24 /*10s*/
5 with primary key
6 as
7 select * from t_mv;
Materialized view created.
SNAPTIME$$字段的值已经修改为第二个物化视图创建的时间(这里也可以解释后面为什么会出现ORA-12034的错误),这是因为第一个物化视图的最后刷新时间比第二个物化创建时间早,用于第一个物化视图刷新。
SQL> select snaptime$$ from mlog$_t_mv;
SNAPTIME$$
-------------------
2012-05-06 01:23:34
SQL> select distinct owner, name mview, master_owner master_owner, last_refresh from dba_mview_refresh_times;
OWNER MVIEW MASTER_OWNER LAST_REFRESH
---------- -------------- ------------------------ ---------------------
TY MV_1 TY 06-MAY-12 01:19:10
TY MV_2 TY 06-MAY-12 01:23:35
SQL> insert into t_mv values (22,'shsnc','咨询');
1 row created.
SQL> select snaptime$$ from mlog$_t_mv;
SNAPTIME$$
---------------------
06-MAY-12 01:23:34
01-JAN-00 00:00:00
这里为了清晰,手动刷新物化视图,模拟物化视图正常刷新。
SQL> exec dbms_mview.refresh('MV_1','F');
PL/SQL procedure successfully completed.
SQL> select snaptime$$ from mlog$_t_mv;
SNAPTIME$$
---------------------
06-MAY-12 01:33:04
SQL> select distinct owner, name mview, master_owner master_owner, last_refresh from dba_mview_refresh_times;
OWNER MVIEW MASTER_OWNER LAST_REFRESH
---------- -------------- ------------------------ ---------------------
TY MV_1 TY 06-MAY-12 01:33:04
TY MV_2 TY 06-MAY-12 01:23:35
SQL> select snaptime$$ from mlog$_t_mv;
SNAPTIME$$
---------------------
06-MAY-12 01:33:04
SQL> exec dbms_mview.refresh('MV_2','F');
PL/SQL procedure successfully completed.
SQL> select distinct owner, name mview, master_owner master_owner, last_refresh from dba_mview_refresh_times;
OWNER MVIEW MASTER_OWNER LAST_REFRESH
---------- -------------- ------------------------ ---------------------
TY MV_1 TY 06-MAY-12 01:33:04
TY MV_2 TY 06-MAY-12 01:38:47
SQL> select snaptime$$ from mlog$_t_mv;
no row selected
这里可以很清楚的看到多个物化视图都是根据同一个物化视图日志来进行刷新的,根据对物化视图日志和物化视图的最后刷新时间来对物化视图刷新进行管理,当基于基表的所有物化视图都刷新后,物化视图日志就会被清除。
SQL> drop materialized view log on t_mv;
Materialized view log dropped.
SQL> exec dbms_mview.refresh('MV_1','F');
BEGIN dbms_mview.refresh('MV_1','F'); END;
*
ERROR at line 1:
ORA-23413: table "TY"."T_MV" does not have a materialized view log
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2563
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2776
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2745
ORA-06512: at line 1
SQL> select distinct owner, name mview, master_owner master_owner, last_refresh from dba_mview_refresh_times;
OWNER MVIEW MASTER_OWNER LAST_REFRESH
---------- -------------- ------------------------ ---------------------
TY MV_1 TY 06-MAY-12 01:48:41
TY MV_2 TY 06-MAY-12 01:38:47
当物化视图日志被删除,此时在刷新物化视图,会报找不到物化视图日志,但是此时物化视图的最后刷新时间也会修改。
SQL> create materialized view log on t_mv;
Materialized view log created.
SQL> exec dbms_mview.refresh('MV_1','F');
BEGIN dbms_mview.refresh('MV_1','F'); END;
*
ERROR at line 1:
ORA-12034: materialized view log on "TY"."T_MV" younger than last refresh
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2563
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2776
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2745
ORA-06512: at line 1
物化视图日志时间不能小于物化视图的最后刷新时间。当我们重新创建物化视图日志,此时物化视图日志时间为4000-01-01 00:00:00,但是物化视图的最后刷新时间为06-MAY-12 01:48:41,此时就会报ORA-12034: materialized view log younger than last refresh。
==========End========================================================

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

请登录后发表评论 登录
全部评论

注册时间:2012-06-04

  • 博文量
    58
  • 访问量
    192582