【问题标题】:Oracle: Is materialized view fast refresh atomic?Oracle:物化视图快速刷新是原子的吗?
【发布时间】:2015-06-13 07:14:02
【问题描述】:

在过去的几个小时里,我已经阅读了很多关于在 Oracle 中刷新 MV 的内容,但我仍然找不到我的问题的答案。想象一下,我在带有更改日志的表顶部有一个 MV 视图。所以这个MV里有3条记录:

COL_ID, COL1
1, "OLD"
2, "OLD"
3, "OLD"

现在假设用于创建 MV 的表中记录 1 的 COL1 的值已更改为“EDITED”。我想执行 fast、in-place 刷新以尽快更新 MV。在具有大约 50M 条记录的实际示例中,刷新大约需要 3 分钟。

想象一下情况。

  1. 刷新过程仍在运行(MV中仍有未修改的记录)。
  2. 无论如何,ID = 1 的记录已被处理,因此它在 MV 中的值为“EDITED”。
  3. 在另一个会话中,执行对 MV 的查询以获取 ID = 1 的记录的值。

结果会给出值为“OLD”或“EDITED”的记录?

我了解,因为这是在刷新机制处理此记录后的就地刷新,所以物化视图中的值将反映原始表中的值(“EDITED”)。但是是否有任何机制(如撤消日志)可以使整个刷新原子化?我的意思是,除非对物化视图进行了所有修改(除非完成刷新过程),如果用户查询在刷新过程中已修改的行,他/她将呈现给一个旧的、缓存的值 - 更改之前。

我认为这种行为对于异地刷新是正确的,但由于前者在时间消耗方面似乎更有效,我很好奇这对于就地转换是否也是正确的。 如果不是默认情况下,有没有办法强制这种原子行为?

----- [编辑]

我在下面的测试中运行测试,看看在刷新过程中我从物化视图得到的结果是否会逐渐变化。

-- 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 重复。另一个线程确实响应了类似的问题,但是对于 complete-refresh,据我了解,它的执行方式与 fast-refresh 非常不同,这里就是这种情况。因此,我不确定是否可以在这里应用相同的解释。

【问题讨论】:

标签: oracle atomic materialized-views


【解决方案1】:

据我所知,Oracle 文档 (http://docs.oracle.com/cd/B19306_01/server.102/b14226/repmview.htm#i31171) - 所有刷新都以原子方式完成:

物化视图的数据不一定始终与其主表或主物化视图的当前数据匹配。物化视图是其主数据的事务(读取)一致反映,因为数据存在于特定时间点(即在创建时或发生刷新时)。

Oracle 通过物化视图组提供更高的读取一致性:

为了保持多个物化视图之间的引用完整性和事务(读取)一致性,Oracle 能够将单个物化视图作为刷新组的一部分进行刷新。刷新组内所有物化视图后,该组内所有物化视图的数据对应同一个事务一致时间点。

【讨论】:

    猜你喜欢
    • 2011-10-20
    • 1970-01-01
    • 2020-03-13
    • 2016-12-11
    • 2013-12-04
    • 2013-06-28
    • 2018-09-04
    • 2012-07-04
    • 2018-09-09
    相关资源
    最近更新 更多