gpt4 book ai didi

Oracle:物化 View 快速刷新是原子的吗?

转载 作者:行者123 更新时间:2023-12-02 04:44:44 28 4
gpt4 key购买 nike

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

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

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

想象一下情况。

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

结果会记录为“OLD”或“EDITED”值吗?

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

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

-----[编辑]

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

-- 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 文档 ( http://docs.oracle.com/cd/B19306_01/server.102/b14226/repmview.htm#i31171 ) 中可以看到 - 所有刷新都是以原子方式完成的:

A materialized view's data does not necessarily match the current data of its master table or master materialized view at all times. A materialized view is a transactionally (read) consistent reflection of its master as the data existed at a specific point in time (that is, at creation or when a refresh occurs).

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

To preserve referential integrity and transactional (read) consistency among multiple materialized views, Oracle has the ability to refresh individual materialized views as part of a refresh group. After refreshing all of the materialized views in a refresh group, the data of all materialized views in the group correspond to the same transactionally consistent point in time.

关于Oracle:物化 View 快速刷新是原子的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29512791/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com