我试图在链接服务器表上创建Materialized view
refresh on commit
,但到目前为止还没有运气。也不确定这是否可能,因为在oracle doc中,它没有说明这是否可能。
我可以使用refresh fast/complete
创建普通的物化视图,但我无法使其与on commit
一起使用。据我从文档中了解,我需要创建MATERIALIZED VIEW LOG ON "table_name"
,但是oracle不要让我把这个表指向链接的一个
我试过的代码:
CREATE MATERIALIZED VIEW LOG ON (SCHEMA_NAME.TABLE_NAME@DATABASE_LINK1)
WITH ROWID (col1, col2, col3, col4, col5),
INCLUDING NEW VALUES;
如果我将REFRESH FAST
更改为REFRESH NEXT TRUNC(SYSDATE) + 1
CREATE MATERIALIZED VIEW MYSCHEME_NAME.TABLE_NAME
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT col1, col2, col3, col4, col5
FROM SCHEMA_NAME.TABLE_NAME@DATABASE_LINK1;
也许有人可以提出另一种方法吗?
我不能使用普通VIEWS
,因为它们太慢了,但我希望数据尽可能地更新,所以在最坏的情况下,我会使用REFRESH NEXT TRUNC(SYSDATE) + 1
尽管我rly不喜欢没有理由刷新视图的想法。
答案 0 :(得分:1)
编辑:我刚刚在
下面添加了“连续查询通知”选项我明白你的意思,但考虑到你一次讨论两个不同的数据库,不仅仅是一个视图,它看起来更像是几乎实时的数据复制问题。
在数据库A上,您拥有的数据一旦被提交,就必须在数据库B上进行复制(稍微转换,就像只有较少的列)。
您可能可以查看Streams(针对复制问题而定制),例如从这里开始:Simple Single-Source Replication Example。就其本质而言,Streams只会在提交时复制更改,而不是更早
但这可能有点过分,因为尽管标题中有“简单”,但你会发现“简单”的例子相当长。
如果您这样做,还要查看Managing Rule-Based Transformations,以便在复制过程中转换数据。
要刷新视图,您可以定义job。为了每天刷新它,但只有当表格发生变化时,您才能跟踪表格的最新SCN(一个告诉记录/块版本的标记)和(每日)刷新您的视图但只有当最新的SCN发生了变化时(这很丑陋,有点像穷人的复制)。所有这些'刷新'逻辑应该放在工作的主体中。
--example of how to select the most current SCN
select MAX(ora_rowscn) from SCHEMA_NAME.TABLE_NAME@DATABASE_LINK1;
--example of how to submit a job executed on a daily basis
exec dbms_job.submit(:v_JobNo,
'a string representing the PL/SQL logic that refreshes the view only when the scn has changed',
TRUNC(SYSDATE)+1,
'TRUNC(SYSDATE)+1'
);
CQN允许定义在查询结果发生变化时调用的回调(参见ORACLE-BASE - DBMS_CHANGE_NOTIFICATION in Oracle 10g Database Release 2)。您可以在远程数据库上使用它来在添加新记录时触发刷新本地数据库上的视图 试一试,因为我不确定远程数据库上的通知是否可以触发驻留在不同数据库(本地数据库)上的回调过程。
这是我将要使用的代码类型(并根据我的需要进行调整;例如查询中的COUNT(*)
有效,但性能很差)
在本地数据库上定义您的视图和刷新后者的过程。将在远程数据库上调用相同的过程作为回调。
drop procedure refresh_materialized_view;
drop materialized view mat_view;
create materialized view mat_view
as select * from monitored_table@remote_db;
/
--this local procedure refreshes the view
create or replace procedure refresh_materialized_view is
begin
--C stands for Complete refresh
DBMS_SNAPSHOT.REFRESH( 'MAT_VIEW','C');
end;
/
在远程DB上注册Change Notification以调用上面定义的回调。注意权限,您可能需要grant change notification
给该数据库上的适当用户
create table monitored_table(n number, ts timestamp);
insert into monitored_table values(1, systimestamp);
commit;
DECLARE
l_regds SYS.CHNF$_REG_INFO;
l_regid NUMBER;
l_qosflags NUMBER;
v_n monitored_table.n%TYPE;
BEGIN
l_qosflags := DBMS_CHANGE_NOTIFICATION.QOS_RELIABLE +
DBMS_CHANGE_NOTIFICATION.QOS_ROWIDS;
--invoke REFRESH_MATERIALIZED_VIEW@MY_DB when a change is detected in the table (see query below)
l_regds := SYS.CHNF$_REG_INFO ('MY_SCHEMA.REFRESH_MATERIALIZED_VIEW@MY_DB', l_qosflags, 0,0,0);
l_regid := DBMS_CHANGE_NOTIFICATION.new_reg_start (l_regds);
--upon changes on the results returned from this query, a notification will be triggered
SELECT count(*)
INTO v_n
FROM monitored_table;
DBMS_CHANGE_NOTIFICATION.reg_end;
END;
/
添加记录以触发通知:
--trigger a Query Change
insert into monitored_table values(2, systimestamp);
insert into monitored_table values(3, systimestamp);
--note that the notification is triggered once for each commit
commit;
最后检查您的观点是否已刷新
select * from mat_view;
无论如何,无论如何,要注意在性能方面要付出的代价。您正在监视包含日志的表,很可能是一个高容量/频率数据,因此您可能不希望经常或每次提交同步您的视图。