场景:
触发刷新的场景有:
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;
- /