物化视图的日志清除是由Oracle自动完成的。Oracle会根据物化视图基表上的注册信息和物化视图的刷新来确定何时删除物化视图日志。
物化视图的注册信息的清除则是在删除物化视图的时候进行,但是对于物化视图建立在远端数据库中的情况,物化视图注册信息的清除可能会复杂一些。
如果物化视图建立在本地,则Oracle拥有所有的数据字典信息,因此,本篇所有的测试都是针对远端物化视图进行的。
首先来看清除物化视图日志的例子。这个操作完全有Oracle进行,即使用户没有物化视图日志的DELETE权限也没有关系。
首先,登陆远端数据库建立测试所用基表和物化视图日志:
SQL> CONN TEST/TEST@TEST2已连接。
SQL> CREATE TABLE T1 (ID NUMBER PRIMARY KEY);
表已创建。
SQL> CREATE MATERIALIZED VIEW LOG ON T1;
实体化视图日志已创建。
下面在本地建立数据库链和物化视图:
SQL> CONN YANGTK/YANGTK已连接。
SQL> CREATE DATABASE LINK TEST2 CONNECT TO TEST IDENTIFIED BY TEST USING 'TEST2';
数据库链接已创建。
SQL> CREATE MATERIALIZED VIEW MV_TEST REFRESH FAST AS SELECT * FROM T1@TEST2;
实体化视图已创建。
下面开始测试:
SQL> INSERT INTO T1@TEST2 VALUES (1);
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT COUNT(*) FROM MLOG$_T1@TEST2;
COUNT(*)
----------
1
SQL> EXEC DBMS_MVIEW.REFRESH('MV_TEST')
PL/SQL 过程已成功完成。
SQL> SELECT COUNT(*) FROM MLOG$_T1@TEST2;
COUNT(*)
----------
0
可见,物化视图日志在物化视图刷新后自动清除了。不过由于数据库链的连接用户是TEST拥有对MLOG$_T1的删除权限。下面建立一个新的用户,只给MLOG$_T1的查询权限:
SQL> CONN TEST/TEST@TEST2已连接。
SQL> CREATE USER AAA IDENTIFIED BY AAA;
用户已创建。
SQL> GRANT CONNECT, RESOURCE TO AAA;
授权成功。
SQL> GRANT SELECT ON T1 TO AAA;
授权成功。
SQL> GRANT SELECT ON MLOG$_T1 TO AAA;
授权成功。
由于我本地数据库的GLOBAL_NAMES设置为FALSE,因此可以建立另一个不同用户的数据库链指向TEST2库。
SQL> CONN YANGTK/YANGTK已连接。
SQL> SHOW PARAMETER GLOBAL_NAMES
NAME TYPE VALUE
------------------------------------ ----------- ----------------------
global_names boolean FALSE
SQL> DROP MATERIALIZED VIEW MV_TEST;
实体化视图已删除。
SQL> CREATE DATABASE LINK TEST2_NEW CONNECT TO AAA IDENTIFIED BY AAA USING 'TEST2';
数据库链接已创建。
SQL> SELECT COUNT(*) FROM TEST.T1@TEST2_NEW;
COUNT(*)
----------
1
SQL> CREATE MATERIALIZED VIEW MV_TEST2 REFRESH FAST AS SELECT * FROM TEST.T1@TEST2_NEW;
实体化视图已创建。
SQL> INSERT INTO T1@TEST2 VALUES (2);
已创建 1 行。
SQL> SELECT COUNT(*) FROM MLOG$_T1@TEST2;
COUNT(*)
----------
1
SQL> EXEC DBMS_MVIEW.REFRESH('MV_TEST2')
PL/SQL 过程已成功完成。
SQL> SELECT COUNT(*) FROM MLOG$_T1@TEST2;
COUNT(*)
----------
0
可见,物化视图日志的清除完全是Oracle的内容操作,与用户的权限没有关系。
物化视图日志的清除依赖于物化视图的注册信息,那么物化视图的注册信息的清除呢:
SQL> SELECT OWNER, NAME, MVIEW_SITE, MVIEW_ID
2 FROM USER_REGISTERED_MVIEWS@TEST2;
OWNER NAME MVIEW_SITE MVIEW_ID
---------- -------------------- ------------------------------ ----------
YANGTK MV_TEST2 YTK.US.ORACLE.COM 64
SQL> DROP MATERIALIZED VIEW MV_TEST2;
实体化视图已删除。
SQL> SELECT OWNER, NAME, MVIEW_SITE, MVIEW_ID
2 FROM USER_REGISTERED_MVIEWS@TEST2;
未选定行
通过测试不难发现在删除物化视图时,Oracle自动将删除的消息传递到主站点,主站点同时清除物化视图的注册信息。
就是这么简单吗,是的。不过前提是创建物化视图时使用的数据库链存在且可用。
如果删除这个数据库链:
SQL> CREATE MATERIALIZED VIEW MV_TEST2 REFRESH FAST AS SELECT * FROM TEST.T1@TEST2_NEW;
实体化视图已创建。
SQL> SELECT OWNER, NAME, MVIEW_SITE, MVIEW_ID
2 FROM USER_REGISTERED_MVIEWS@TEST2;
OWNER NAME MVIEW_SITE MVIEW_ID
---------- -------------------- ------------------------------ ----------
YANGTK MV_TEST2 YTK.US.ORACLE.COM 65
SQL> DROP DATABASE LINK TEST2_NEW;
数据库链接已删除。
SQL> DROP MATERIALIZED VIEW MV_TEST2;
实体化视图已删除。
SQL> SELECT OWNER, NAME, MVIEW_SITE, MVIEW_ID
2 FROM USER_REGISTERED_MVIEWS@TEST2;
OWNER NAME MVIEW_SITE MVIEW_ID
---------- -------------------- ------------------------------ ----------
YANGTK MV_TEST2 YTK.US.ORACLE.COM 65
在删除数据库链之后删除物化视图,删除物化视图的动作本身并不会报错,但是主站点的物化视图日志不会被清除。
另外Oracle没有聪明到利用其它的等价数据库链的地步,它只会使用物化视图定义中指定的那个数据库链。
下面继续观察物化视图日志的清除情况:
SQL> INSERT INTO T1@TEST2 VALUES (3);
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT COUNT(*) FROM MLOG$_T1@TEST2;
COUNT(*)
----------
1
由于物化视图注册信息的存在,物化视图
下面重建数据库链和刚才删除的物化视图:
SQL> CREATE DATABASE LINK TEST2_NEW CONNECT TO AAA IDENTIFIED BY AAA USING 'TEST2';
数据库链接已创建。