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');
   
第二個存儲過程執行以後,與基表有關的所有的物化視圖需要完全刷新;
第一個存儲過程隻影響指定的物化視圖,這個被影響的物化視圖也需要完全刷新;
具體的用法不是很清楚,歡迎交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章