场景:
触发刷新的场景有:
1.刚开始对数据库进行的初始化刷新
2.一个commit
3.根据一个预定计划的job来对物化视图进行刷新
问题的场景,是通过一个预定的计划来对物化视图做刷新操作。
点击(此处)折叠或打开
- CREATE MATERIALIZED VIEW TESTMV
- NOLOGGING
- BUILD DEFERRED
- REFRESH COMPLETE ON DEMAND
- NEXT trunc(sysdate + 1,'dd') + (1/24)
- AS
- SELECT * FROM EMP;
提示:NEXT的语法会制定物化视图在凌晨一点钟执行刷新操作。
如果job失败的话,job子系统会再次执行它。
这将会导致一个场景,系统会变得很忙,总是想完成这个刷新操作,特别是物化视图比上述所说的还要复杂的时候、
解决方案:
以下的sql语句可以知道哪些job是在当前被计划中的:
点击(此处)折叠或打开
- COLUMN JOB HEADING 'Job ID' FORMAT 999999
- COLUMN PRIV_USER HEADING 'Privilege|Schema' FORMAT A10
- COLUMN RNAME HEADING 'Refresh|Group|Name' FORMAT A10
- COLUMN ROWNER HEADING 'Refresh|Group|Owner' FORMAT A10
- COLUMN BROKEN HEADING 'Broken?' FORMAT A7
-
- SELECT J.JOB,
- J.PRIV_USER,
- R.ROWNER,
- R.RNAME,
- J.BROKEN
- FROM DBA_REFRESH R, DBA_JOBS J
- WHERE R.JOB = J.JOB
- ORDER BY 1;
- Refresh Refresh
- Privilege Group Group
- Job ID Schema Owner Name Broken?
- ------- ---------- ------------ ---------- -------
- 26 SCOTT SCOTT TESTMV N
再根据job id号,看看下面又发生了什么
- col last_date format a10
- col last_sec format a10
- col next_sec format a10
- col interval format a20
- col what format a30
- col what broken a10
-
- select job,last_date, last_sec,
- total_time,next_date,next_sec,what,interval,broken
- from DBA_JOBS
- where job=n;
- SELECT * FROM V$MVREFRESH
你会看到相似的输出:
- Session Serial Materialized
- Identifier Number Owner View
- ---------- ------- --------------- -------------------------
- 19 233 SCOTT TESTMV
这个例子说明被scott用户所拥有的物化视图TESTMV正在被刷新中,你可以执行下面的语句取消当前回话的刷新操作。
- ALTER SYSTEM KILL SESSION 19,233;
下面是干货,会话failed之后,job会重新的re-schedule的刷新操作。
为了防止这个情况的发生,你需要在取消操作之前先mark一下broken,让job不再re-scheuled。
通过以下的操作,操作的用户是MV的拥有者,而不是sysdba
- sqlplus scott/tiger(这个用户是你实际运行的用户)
- SQL> BEGIN
- DBMS_JOB.BROKEN ( n, true);
- commit;
- END;
- /
现在可以重新测试一下job是否为broken了:
- Refresh Refresh
- Privilege Group Group
- Job ID Schema Owner Name Broken?
- ------- ---------- ------------ ---------- -------
- 26 SCOTT SCOTT TESTMV Y
- ALTER SYSTEM KILL SESSION 19,233;
这个刷新操作再也不会发生,除非你又重新标记job为"not broken",想如下所做:
- sqlplus scott/tiger
- SQL> BEGIN
- DBMS_JOB.BROKEN ( n, false);
- commit;
- END;
- /