ORA-12048:刷新实体化视图

当系统中存在多个物化视图,使用刷新组会大大简化物化视图的刷新,只需要将同一时间同步的物化视图全都放到一个刷新组中既可。

在9i中,使用刷新组方便的时候有一个缺点,如果其中一个物化视图报错,Oracle给出的错误信息并没有说明是哪个物化视图出了问题。

这篇文章讨论对于本地物化视图,如何定位刷新组中刷新失败的物化视图。

先构造一个简单的例子:

SQL> SELECT * FROM V$VERSION;

BANNER
 ----------------------------------------------------------------
Oracle9iEnterpriseEdition Release9.2.0.4.0 -Production
PL/SQL Release 9.2.0.4.0 - Production
CORE    9.2.0.3.0       Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production

SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

会话已更改。

SQL> CREATE TABLE T1 (ID PRIMARY KEY, NAME) AS SELECT ROWNUM, TNAME FROM TAB;

表已创建。

SQL> CREATE TABLE T2 (ID PRIMARY KEY, NAME) AS SELECT ROWNUM, TNAME FROM TAB;

表已创建。

SQL> CREATE TABLE T3 (ID PRIMARY KEY, NAME) AS SELECT ROWNUM, TNAME FROM TAB;

表已创建。

SQL> CREATE MATERIALIZED VIEW LOG ON T1;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW LOG ON T2;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW LOG ON T3;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW MV_T1 REFRESH FAST AS SELECT * FROM T1;

实体化视图已创建。

SQL> CREATE MATERIALIZED VIEW MV_T2 REFRESH FAST AS SELECT * FROM T2;

实体化视图已创建。

SQL> CREATE MATERIALIZED VIEW MV_T3 REFRESH FAST AS SELECT * FROM T3;

实体化视图已创建。

SQL> EXEC DBMS_REFRESH.MAKE('REP_TEST', 'MV_T1,MV_T2,MV_T3', SYSDATE, 'SYSDATE + 1')

PL/SQL过程已成功完成。

SQL> INSERT INTO T1 VALUES (100, 'A');

已创建1行。

SQL> INSERT INTO T2 VALUES (100, 'A');

已创建1行。

SQL> INSERT INTO T3 VALUES (100, 'A');

已创建1行。

SQL> EXEC DBMS_REFRESH.REFRESH('REP_TEST')

PL/SQL过程已成功完成。

如果对表T2进行了修改:

SQL> ALTER TABLE T2 MODIFY NAME VARCHAR2(32);

表已更改。

SQL> INSERT INTO T1 VALUES (101, 'B');

已创建1行。

SQL> INSERT INTO T2 VALUES (101, LPAD('B', 32, 'B'));

已创建1行。

SQL> INSERT INTO T3 VALUES (101, 'B');

已创建1行。

SQL> COMMIT;

提交完成。

SQL> SELECT MVIEW_NAME, LAST_REFRESH_DATE, STALENESS FROM USER_MVIEWS;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS
     --------------------------             -------------------                  ------------------
         MV_T1                                   2008-01-23 19:22:43     NEEDS_COMPILE
         MV_T2                                   2008-01-23 19:22:43     NEEDS_COMPILE
         MV_T3                                   2008-01-23 19:22:43     NEEDS_COMPILE

SQL> EXEC DBMS_REFRESH.REFRESH('REP_TEST')
                           BEGIN DBMS_REFRESH.REFRESH('REP_TEST'); END;

 第1行出现错误:

 ORA-12008:实体化视图的刷新路径中存在错误
        ORA-01401:插入的值对于列过大
        ORA-06512:在"SYS.DBMS_SNAPSHOT", line 794
        ORA-06512:在"SYS.DBMS_SNAPSHOT", line 851
        ORA-06512:在"SYS.DBMS_IREFRESH", line 683
        ORA-06512:在"SYS.DBMS_REFRESH", line 195
        ORA-06512:在line 1

这时就会出现刷新错误,而Oracle给出的错误信息虽然很明确,但是并没有指出具体是那张表出现了错误,而只有找到错误的表才能定位并解决问题。

其实这个问题的解决方法有很多,比如写一个过程,对刷新组中所有的物化视图进行依次刷新,出现错误时弹出异常。也可以利用SQL_TRACE、系统级错误触发器等手段。

不过最方便的方法莫过于查询USER_MVIEWS视图:

SQL> SELECT MVIEW_NAME, LAST_REFRESH_DATE, STALENESS FROM USER_MVIEWS;

MVIEW_NAME                     LAST_REFRESH_DATE   STALENESS
      ------------------------------       -------------------                  --------------------
MV_T1                          2008-01-23 19:24:56                      FRESH
MV_T2                          2008-01-23 19:22:43                      STALE
MV_T3                          2008-01-23 19:22:43                      NEEDS_COMPILE

对于刷新成功的物化视图,LAST_REFRESH_DATE会比刷新组进行刷新的时间大。而对于还没有刷新的物化视图,STALENESS的状态应该是NEEDS_COMPILE或者FRESH。而对于基表发生了变化导致物化视图刷新失败,则会导致物化视图的STALENESS变为STALE。通过这种方法就可以简单的定位刷新出现错误的物化视图。

当然上面的办法是对9i而言,而在10g中,Oracle返回的错误信息更加详细,可以直接定位到错误的表和原因:

SQL> SELECT * FROM V$VERSION;

BANNER

---------------------------------------------------------------
Oracle Database10gEnterpriseEdition Release10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production

CORE    10.2.0.3.0      Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production

SQL> CREATE TABLE T1 (ID PRIMARY KEY, NAME) AS SELECT ROWNUM, TNAME FROM TAB;

表已创建。

SQL> CREATE TABLE T2 (ID PRIMARY KEY, NAME) AS SELECT ROWNUM, TNAME FROM TAB;

表已创建。

SQL> CREATE TABLE T3 (ID PRIMARY KEY, NAME) AS SELECT ROWNUM, TNAME FROM TAB;

表已创建。

SQL> CREATE MATERIALIZED VIEW LOG ON T1;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW LOG ON T2;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW LOG ON T3;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW MV_T1 REFRESH FAST AS SELECT * FROM T1;

实体化视图已创建。

SQL> CREATE MATERIALIZED VIEW MV_T2 REFRESH FAST AS SELECT * FROM T2;

实体化视图已创建。

SQL> CREATE MATERIALIZED VIEW MV_T3 REFRESH FAST AS SELECT * FROM T3;

实体化视图已创建。

SQL> EXEC DBMS_REFRESH.MAKE('REP_TEST', 'MV_T1,MV_T2,MV_T3', SYSDATE, 'SYSDATE + 1')

PL/SQL过程已成功完成。

SQL> INSERT INTO T1 VALUES (100, 'A');

已创建1行。

SQL> INSERT INTO T2 VALUES (100, 'A');

已创建1行。

SQL> INSERT INTO T3 VALUES (100, 'A');

已创建1行。

SQL> EXEC DBMS_REFRESH.REFRESH('REP_TEST')

PL/SQL过程已成功完成。

SQL> ALTER TABLE T2 MODIFY NAME VARCHAR2(35);

表已更改。

SQL> INSERT INTO T2 VALUES (101, LPAD('A', 35, 'A'));

已创建1行。

SQL> COMMIT;

提交完成。

SQL> EXEC DBMS_REFRESH.REFRESH('REP_TEST')
BEGIN DBMS_REFRESH.REFRESH('REP_TEST'); END;

*
第1行出现错误:
ORA-12048:刷新实体化视图"TEST"."MV_T2"时出错
ORA-12899:列"TEST"."MV_T2"."NAME"的值太大(实际值: 35,最大值: 30)
ORA-06512:在"SYS.DBMS_SNAPSHOT", line 2254
ORA-06512:在"SYS.DBMS_SNAPSHOT", line 2460
ORA-06512:在"SYS.DBMS_IREFRESH",

你可能感兴趣的:(Oracle数据库资料)