oracle 物化视图日志不自动清除

清理物化视图日志步骤:
以scott用户下的一张mview_1为基表建立两个物化视图,然后unregister其中一个(EXEC DBMS_MVIEW.UNREGISTER_MVIEW('MING', 'TARGET_MVIEW_1', 'OGG1')。向基表中出入三条数据,提交后查看日志表:
创建dblink
create database link scott_link_1
connect to scott
identified by oracle
using 'systest';

create database link scott_link_2
connect to scott
identified by oracle
using 'systest';

scott用户创建物化视图日志:
SQL> sho user
USER is "SCOTT"
SQL> desc mview_1
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
ID                                        NOT NULL NUMBER
NAME                                               VARCHAR2(20)

SQL> create materialized view log on mview_1 with primary key;

Materialized view log created.

SQL> select table_name from user_tables where table_name like 'MLOG$%';

TABLE_NAME
------------------------------
MLOG$_MVIEW_1

创建物化视图:
SQL> sho user
USER is "MING"
SQL> create materialized view target_mview_1 on prebuilt table refresh fast on demand with primary key start with sysdate next
  2  to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),'10:25:00'),'dd-mm-yyyy hh24:mi:ss') as
  3  select * from scott.mview_1@scott_link_1;

Materialized view created.

SQL> create materialized view target_mview_2 build immediate refresh fast on demand with primary key start with sysdate next
  2  to_date(concat(to_char(sysdate+1,'dd-mm-yyyy'),'10:25:00'),'dd-mm-yyyy hh24:mi:ss') as
  3  select * from scott.mview_1@scott_link_2;

Materialized view created.

scott用户向mview_1中插入4条数据,然后查询日志表:

SQL> select count(*) from scott.MLOG$_MVIEW_1;

  COUNT(*)
----------
         4
存在了4条记录。

物化视图日志存储在"MLOG$_"为开头的表名中。

首先查看有多少物化视图注册到了刷新机制中
SQL> select OWNER,NAME,MVIEW_SITE,MVIEW_ID from DBA_REGISTERED_MVIEWS;

OWNER           NAME                           MVIEW_SITE                       MVIEW_ID
--------------- ------------------------------ ------------------------------ ----------
SYSMAN          MGMT_ECM_MD_ALL_TBL_COLUMNS    SEEDDATA                                0
SH              CAL_MONTH_SALES_MV             OGG1                                   21
SH              FWEEK_PSCAT_SALES_MV           OGG1                                   22
MING            TARGET_MVIEW_1                 OGG1                                   87
MING            TARGET_MVIEW_2                 OGG1                                   88

现在删掉一条db_link:
SQL> drop database link scott_link_2;

Database link dropped.



查看基表上的物化视图刷新依赖
SQL> SELECT * FROM DBA_BASE_TABLE_MVIEWS;

OWNER           MASTER                         MVIEW_LAST_REFRESH_   MVIEW_ID
--------------- ------------------------------ ------------------- ----------
SCOTT           MVIEW_1                        2018-01-21 04:00:02         87
SCOTT           MVIEW_1                        2018-01-21 04:06:12         88



增量刷新两个物化视图
SQL> exec dbms_mview.refresh('TARGET_MVIEW_1');

PL/SQL procedure successfully completed.

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

*
ERROR at line 1:
ORA-02019: connection description for remote database not found
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

这时候TARGET_MVIEW_2已经不能刷新了;

物化视图日志:
SQL> select count(*) from scott.MLOG$_MVIEW_1;

  COUNT(*)
----------
         4
正常来说,基于一张表的所有物化视图刷新以后日志表会被清空,现在因为有一个物化视图因为db_link删除而导致刷新失败,物化视图日志是不会自动清除的。
这时候的解决思路通常是:
1.删除无法刷新的物化视图
2.删除无法刷新的物化视图的注册信息

这里我采用第二种方法;
SQL> EXEC DBMS_MVIEW.UNREGISTER_MVIEW('MING', 'TARGET_MVIEW_2', 'OGG1');

PL/SQL procedure successfully completed.

SQL> select OWNER,NAME,MVIEW_SITE,MVIEW_ID from DBA_REGISTERED_MVIEWS;

OWNER           NAME                           MVIEW_SITE                       MVIEW_ID
--------------- ------------------------------ ------------------------------ ----------
SYSMAN          MGMT_ECM_MD_ALL_TBL_COLUMNS    SEEDDATA                                0
SH              CAL_MONTH_SALES_MV             OGG1                                   21
SH              FWEEK_PSCAT_SALES_MV           OGG1                                   22
MING            TARGET_MVIEW_1                 OGG1                                   87
可以看到MVIEW_ID=88的物化视图已经没有了。

清除日志,注意千万不要写错mview_id,不然后续刷新会报错。
SQL> EXEC DBMS_MVIEW.PURGE_MVIEW_FROM_LOG(88);

PL/SQL procedure successfully completed.

这是查询日志:
SQL> select count(*) from scott.MLOG$_MVIEW_1;

  COUNT(*)
----------
         0
发现物化视图日志已经清空了。

基表再插入一条数据:
SQL> /
  COUNT(*)
----------
         1
SQL> exec dbms_mview.refresh('TARGET_MVIEW_1');

PL/SQL procedure successfully completed.

再次查询发现物化视图日志,已经自动被清除了:
SQL> /

  COUNT(*)
----------
         0
再次查询刷新时间:
SQL> SELECT * FROM DBA_BASE_TABLE_MVIEWS;

OWNER           MASTER                         MVIEW_LAST_REFRESH_   MVIEW_ID
--------------- ------------------------------ ------------------- ----------
SCOTT           MVIEW_1                        2018-01-21 04:26:20         87
已经没有88那条信息了。
当然了,表还是在的,只是数据不对了。
SQL> select count(*) from TARGET_MVIEW_2;

  COUNT(*)
----------
         9
这时重建一下删除的db_link,再尝试刷新一下TARGET_MVIEW_2:
SQL> exec dbms_mview.refresh('TARGET_MVIEW_2');
BEGIN dbms_mview.refresh('TARGET_MVIEW_2'); END;

*
ERROR at line 1:
ORA-12034: materialized view log on "SCOTT"."MVIEW_1" younger than last refresh
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

还是报错,报错跟SYS.DBMS_SNAPSHOT有关;DBMS_MVIEW是DBMS_SNAPSHOT的同义词,所以应该是清楚了注册信息的原因。
重新注册,以下摘自官方文档:
DBMS_MVIEW.REGISTER_MVIEW (
   mviewowner  IN   VARCHAR2,
   mviewname   IN   VARCHAR2,
   mviewsite   IN   VARCHAR2,
   mview_id    IN   DATE | BINARY_INTEGER,
   flag        IN   BINARY_INTEGER,
   qry_txt     IN   VARCHAR2,
   rep_type    IN   BINARY_INTEGER := DBMS_MVIEW.REG_UNKNOWN);
但是按照官方文档的写法总是报错:   
execute DBMS_MVIEW.REGISTER_MVIEW('MING', 'TARGET_MVIEW_2', 'OGG1',88,33, 'select * from scott.mview_1@scott_link_2', 'DBMS_MVIEW.REG_UNKNOWN');
以下摘自MOS:
How to REGISTER and UNREGISTER a Materialized View - Testcase (文档 ID 1393276.1)

SQL> select s.sowner OWNER, s.vname NAME, snapid,
  2  decode(bitand(s.flag,1), 0, 'NO', 'YES') CAN_USE_LOG,
  3  decode(bitand(s.flag,2), 0, 'NO', 'YES') UPDATABLE,
  4  decode(bitand(s.flag,16), 16, 'ROWID',
  5  (decode(bitand(s.flag,32), 32, 'PRIMARY KEY',
  6  (decode(bitand(s.flag,536870912), 536870912, 'OBJECT ID',
  7  'UNKNOWN'))))) REFRESH_METHOD
  8  from sys.snap$ s where s.vname='TARGET_MVIEW_2';

OWNER           NAME                               SNAPID CAN UPD REFRESH_METHOD
--------------- ------------------------------ ---------- --- --- ---------------
MING            TARGET_MVIEW_2                         88 YES NO  PRIMARY KEY

So if we have an mview with primary key, and NOT UPDATABLE and FAST refreshable then this will be:

can_use_log yes 1
updatable no 0
primary key yes 32

So we add these together and get 33 so this is the value for the FLAG column.

注册:
execute dbms_MVIEW.register_mview(-
'MING', -
'TARGET_MVIEW_2',-
'OGG1',-
88,-
33,-
'select * from scott.mview_1@scott_link_2');

PL/SQL procedure successfully completed.
再次查询注册信息,发现已经注册回来了,如下:
21:19:38 SQL> col mview_site for a20
21:19:53 SQL> select OWNER,NAME,MVIEW_SITE,MVIEW_ID from DBA_REGISTERED_MVIEWS;

OWNER                          NAME                           MVIEW_SITE             MVIEW_ID
------------------------------ ------------------------------ -------------------- ----------
SYSMAN                         MGMT_ECM_MD_ALL_TBL_COLUMNS    SEEDDATA                      0
SH                             CAL_MONTH_SALES_MV             OGG1                         21
SH                             FWEEK_PSCAT_SALES_MV           OGG1                         22
MING                           TARGET_MVIEW_2                 OGG1                         88
MING                           TARGET_MVIEW_1                 OGG1                         87

5 rows selected.
基表插入几行数据,再次尝试刷新:
21:23:07 SQL> EXEC dbms_mview.REFRESH('TARGET_MVIEW_1')

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.37
21:25:34 SQL> EXEC dbms_mview.REFRESH('TARGET_MVIEW_2')
BEGIN dbms_mview.REFRESH('TARGET_MVIEW_2'); END;

*
ERROR at line 1:
ORA-12034: materialized view log on "SCOTT"."MVIEW_1" younger than last refresh
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

这个报错也很容易理解:
因为unregister之后,数据量变化过,我们清除来了一次物化视图日志,所以有gap,这里执行一次完全刷新应该就可以了,试一下:
21:29:31 SQL> exec dbms_mview.refresh('TARGET_MVIEW_2','C');

PL/SQL procedure successfully completed.

验证一下:
基表:
21:27:14 SQL> select count(*) from mview_1;

  COUNT(*)
----------
        17

1 row selected.

物化视图:
21:30:05 SQL> select count(*) from target_mview_1 union all select count(*) from target_mview_2;

  COUNT(*)
----------
        17
        17

2 rows selected.

在查看官方文档的时候发现有两个purge log相关的存储过程,
DBMS_MVIEW.PURGE_MVIEW_FROM_LOG (
   mview_id       IN   BINARY_INTEGER);

DBMS_MVIEW.PURGE_MVIEW_FROM_LOG (
   mviewowner     IN   VARCHAR2,
   mviewname      IN   VARCHAR2,
   mviewsite      IN   VARCHAR2);
上面两个是一个。   
DBMS_MVIEW.PURGE_LOG (
   master        IN   VARCHAR2,
   num           IN   BINARY_INTEGER := 1,
   flag          IN   VARCHAR2       := 'NOP');
   
第二个存储过程执行以后,与基表有关的所有的物化视图需要完全刷新;
第一个存储过程只影响指定的物化视图,这个被影响的物化视图也需要完全刷新;
具体的用法不是很清楚,欢迎交流。

你可能感兴趣的:(Oracle数据库,Oracle体系结构,管理方案对象)