關于MV刷新的問題
?
??? 最近在工作中遇到一個問題,是關于物化視圖的刷新的,對實際數據產生了比較大的影響。雖然犯得錯誤很低級,主要是由于對一些概念的不清晰造成的,但是仍然覺得有必要將這個問題記下來,以免悲劇再次發生。
?
?
?
?
??? 這個錯誤還需要從materialized view的創建開始追溯,因為如果在create materialized view語句中加入start with 和 next 子句的話,創建MV的過程中會自動創建一個job,制定定期刷新計劃,例如:
?
create materialized view t1_mv refresh fast
start with to_date('21-07-2009 17:15:00', 'dd-mm-yyyy hh24:mi:ss')
? next TRUNC(SYSDATE,'HH')+375/1440
? with primary key
??? as select * from t1;
?
SQL> select job, schema_user, interval, what from all_jobs;
?
?????? JOB SCHEMA_USER??????? INTERVAL??????????????????????????? WHAT
---------- ------------------ ----------------------------------- ----------------------------------------------
??????? 21 WANGXIAOQI???????? TRUNC(SYSDATE,'HH')+375/1440??????? dbms_refresh.refresh('"WANGXIAOQI"."T1_MV"');
?
SQL>
?
??? 可以看到,這個job中的執行內容是:dbms_refresh.refresh('"WANGXIAOQI"."T1_MV"'); 而不是我們普通手動刷新MV時用的 dbms_mview.refresh 。
?
?
?
?
?
?
??? 再來研究一下dbms_refresh這個數據包,這個包是用于產生一個刷新組以方便MV一組為單位統一刷新的。而當MV被制定刷新策略的方式指定時,會自動創建一個刷新組,并將該MV添加至這個刷新組中,所以job可以使用dbms_refresh.refresh來進行刷新。可以來看一下:
?
SQL> select rowner, rname, job, interval from all_refresh where rname = 'T1_MV';
?
ROWNER?????????????? RNAME?????????????????? JOB INTERVAL
-------------------- ---------------- ---------- ----------------------------------------
WANGXIAOQI?????????? T1_MV??????????????????? 21 TRUNC(SYSDATE,'HH')+375/1440
?
??? 再看這個組的成員:
?
SQL> select rowner, rname, job, interval from all_refresh_children where rname = 'T1_MV';
?
ROWNER?????????????? RNAME?????????????????? JOB INTERVAL
-------------------- ---------------- ---------- ----------------------------------------
WANGXIAOQI?????????? T1_MV??????????????????? 21 TRUNC(SYSDATE,'HH')+375/1440
?
??? 可以看到只有這個物化視圖本身。
?
?
?
?
?
?
??? 這新一次的物化視圖創建中,沒有指定執行時間,而是單純得創建,所以Oracle不會創建刷新組,如下:
?
SQL>
SQL> create materialized view t1_mv_2 refresh fast
? 2????? as select * from t1;
?
Materialized view created
SQL> select rowner, rname, job, interval from all_refresh_children where rname = 'T1_MV_2';
?
ROWNER?????????????? RNAME?????????????????? JOB INTERVAL
-------------------- ---------------- ---------- ----------------------------------------
SQL>
?
??? 所以,如果對dbms_refresh了解不清的情況下,會造成無法刷新的情況,如果對沒有創建刷新組的對象進行刷新就報錯:
?
SQL> exec dbms_refresh.refresh('T1_MV_2');
?
begin dbms_refresh.refresh('T1_MV_2'); end;
?
ORA-23404: refresh group "WANGXIAOQI"."T1_MV_2" does not exist
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 95
ORA-06512: at "SYS.DBMS_REFRESH", line 23
ORA-06512: at "SYS.DBMS_REFRESH", line 195
ORA-06512: at line 2
?
SQL> exec dbms_mview.refresh('T1_MV_2');
?
PL/SQL procedure successfully completed
?
?
??? 另外還需要注意一點,如果刪除了某個MV,則會連同創建的fresh group同時刪除,需要在實際操作中注意。
?
?
?
?