过去几个小时我已经阅读了很多关于在Oracle中刷新MV的内容,但我仍然无法找到问题的答案。想象一下,我在一个带有更改日志的表顶部有一个MV视图。所以这个MV中有三条记录:
COL_ID, COL1
1, "OLD"
2, "OLD"
3, "OLD"
现在假设COL1的值已更改为“EDITED”,表示用于创建MV的表中的记录1。我想执行快速,就地刷新以尽快更新MV。在具有大约50M记录的现实生活中,这将花费大约3分钟来刷新。
想象一下情况。
结果会记录值“OLD”或“EDITED”吗?
我理解,因为这是刷新机制处理此记录后的就地刷新,物化视图中的值将反映原始表中的值(“EDITED”)。但有没有任何机制(如撤消日志)会使整个刷新原子?我的意思是,除非对物化视图进行所有修改(除非刷新过程完成),否则如果用户查询在刷新过程中已经修改的行,他/她将被呈现给旧的,缓存价值 - 改变之前。
我认为这个bevahiour对于不合适的刷新是正确的,但是由于前者似乎在时间消耗方面更有效,我很好奇这对于就地转换是否也是如此。 如果不是默认情况下,有没有办法强制这种原子行为?
----- [编辑]
我在测试后运行测试,看看在刷新过程中我从物化视图中得到的结果是否会逐渐变化。
-- create table
create table MV_REFRESH_ATOMICITY_TEST
(
id NUMBER,
value NUMBER
)
-- populate initial data
-- delete from MV_REFRESH_ATOMICITY_TEST
declare
begin
for i in 1..10000000 loop
insert into MV_REFRESH_ATOMICITY_TEST values(i, 0);
end loop;
end;
-- check if equal zero and 1M
select sum(value) from MV_REFRESH_ATOMICITY_TEST
select to_char(count(*),'999,999,999') as COUNT from MV_REFRESH_ATOMICITY_TEST
-- create mv logs on the table
-- drop materialized view log on MV_REFRESH_ATOMICITY_TEST;
create materialized view log on MV_REFRESH_ATOMICITY_TEST with rowid;
-- create mv on top
-- drop materialized view MV_REFRESH_ATOMICITY_TEST_MV
create materialized view MV_REFRESH_ATOMICITY_TEST_MV
refresh fast on demand with rowid
as
select
fact.*,
fact.ROWID "FACT_ROWID"
from
MV_REFRESH_ATOMICITY_TEST fact
-- check if equals zero and 10M
select sum(value) from MV_REFRESH_ATOMICITY_TEST_MV
select to_char(count(*),'999,999,999') as COUNT from MV_REFRESH_ATOMICITY_TEST_MV
-- change value for first million records, 1 milion records in the middle, last milion of records
update MV_REFRESH_ATOMICITY_TEST set value = 1 where id between 1 and 1000000
update MV_REFRESH_ATOMICITY_TEST set value = 1 where id between 5000001 and 6000000
update MV_REFRESH_ATOMICITY_TEST set value = 1 where id between 9000001 and 10000000
-- check if equals 3.000.000
select to_char(sum(value),'999,999,999') as "SUM" from MV_REFRESH_ATOMICITY_TEST
-- check if equals 3.000.000
select to_char(count(*),'999,999,999') from MLOG$_MV_REFRESH_ATOMICITY;
--select * from MLOG$_MV_REFRESH_ATOMICITY;
-- while refreshing mv
-- exec dbms_mview.refresh('MV_REFRESH_ATOMICITY_TEST_MV', 'F');
-- below sum should be equal 0
select
( select sum(value) from MV_REFRESH_ATOMICITY_TEST_MV ) "SUM",
( select count(*) from MV_REFRESH_ATOMICITY_TEST_MV ) "NUMBER OF RECORDS"
from dual
所以我通过不断执行最后一个select语句发现的是,SUM值发生变化的唯一时间,它已经被3M更改,这意味着所有记录都已经一次性更改 - 原子。
尽管如此,我并不是100%肯定我可以相信这个实验,因为在某些时候执行这些选择查询需要大约40秒。整个刷新语句需要911秒才能执行。
[编辑]
此问题已标记为this thread的可能副本。另一个线程确实响应了类似的问题,但是对于完全刷新,我的理解是以与快速刷新完全不同的方式执行,这就是这里的情况。因此,我不确定这里是否可以应用相同的解释。
答案 0 :(得分:2)
从Oracle文档(http://docs.oracle.com/cd/B19306_01/server.102/b14226/repmview.htm#i31171)可以看出 - 所有刷新都是以原子方式完成的:
物化视图的数据不一定与其主表或主物化视图的当前数据匹配。物化视图是其主数据的事务(读)一致反映,因为数据存在于特定时间点(即创建时或刷新时)。
Oracle为物化视图组提供了更高的读取一致性:
为了保持多个物化视图之间的参照完整性和事务性(读取)一致性,Oracle能够刷新单个物化视图作为刷新组的一部分。刷新刷新组中的所有物化视图后,组中所有物化视图的数据对应于事务上一致的相同时间点。