ORACLE物化视图--物化视图日志如何避免系统时间变化带来的影响

ORACLE物化视图--物化视图日志如何避免系统时间变化带来的影响

转载
标签: 

时间

 

系统

 

如何

 

影响

 

杂谈

 

物化视图通过利用物化视图日志来进行快速刷新。通过记录在物化视图日志中的SNAPTIME$$列来判断这个记录是否需要刷新。

一般情况下,如果物化视图日志支持多个物化视图刷新,当执行刷新操作时,Oracle会将SNAPTIME$$字段的值更新为当前的时间。这样,同一个物化视图再次刷新时,只要刷新那些SNAPTIME$$大于上次刷新时间的记录就可以了。

仔细考虑一下,就会发现两个问题。一、如果物化视图处于不同的服务器中,且这些服务器的系统时间都不相同,Oracle怎么才能保证数据的一致性呢?二、Oracle通过时间列来判断哪些记录需要刷新,而Oracle的SYSDATE时间取自系统时间,那么如果系统时间进行了更改,Oracle如何保证刷新不会丢失数据也不会重复刷新呢。


经过测试,找到了Oracle避免问题产生的方法。对于一:由于时间不同步或者物化视图所在站点处于不同时区,每个物化视图服务器所处的时间可能都不相同。因此,Oracle在记录时间时都取的是本机的SYSDATE时间。也就是说,不过那个物化视图进行了刷新,物化视图日志中的MLOG$列记录的都是本机的SYSDATE时间,主站点上记录各个物化视图的最后刷新时间也采用的都是本机时间。对于各个物化视图站点,它们记录在数据字典中的物化视图上次刷新时间都是它们服务器自己的本机时间。所有的时间列都依据本机的系统时间,从而避免了时间不同带来的影响。

对于第二点:无论是主站点上还是物化视图站点当发生系统时间变化时都依据如下规律。如果将系统时间向后调,比如将14:00点调到15:00点、将3月9日调到3月10日,则在记录时间时不发生变化。如果系统时间往回调,比如将14:00点调到13:00点、将3月9日调到3月8日,则在记录时间的时候会把上次的刷新时间增加1秒保存在记录中。换句话说,无论是物化视图日志中的SNAPTIME$$列,还是USER_BASE_TABLE_MVIEWS中的MVIEW_LAST_REFRESH_TIME列,里面记录的时间点都是递增的,本次操作的时间值是系统当前时间与上次操作的时间值加1秒这两个时间中大的那个。

下面看看测试的结果:

SQL> conn yangtk/yangtk@test
已连接。
SQL> create table test (id number primary key);

表已创建。

SQL> create materialized view log on test;

实体化视图日志已创建。

SQL> create materialized view mv_test_yangtingkun refresh fast
2 as select * from test;

实体化视图已创建。

在本地数据库上建好测试表和一个物化视图。

SQL> conn test/[email protected]
已连接。
SQL> create database link test.yangtingkun connect to yangtk identified by yangtk using '172.25.3.174';

数据库链接已创建。

SQL> select * from global_name;

GLOBAL_NAME
------------------------------------------------
C.ABC.COM

SQL> select * from [email protected];

GLOBAL_NAME
------------------------------------------------
TEST.YANGTINGKUN

SQL> create materialized view mv_test_cabccom refresh fast
2 as select * from [email protected];

实体化视图已创建。

在另一台服务器的数据库上建立另一个物化视图。

SQL> conn yangtk/yangtk@test
已连接。
SQL> insert into test values (1);

已创建1 行。

SQL> commit;

提交完成。

SQL> exec dbms_mview.refresh('mv_test_yangtingkun');

PL/SQL 过程已成功完成。

SQL> select idhttp://www.ckhmagic.com/, to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') now_time,
2 to_char(snaptime$$, 'yyyy-mm-dd hh24:mi:ss') snaptime$$ from mlog$_test;

ID NOW_TIME SNAPTIME$$
---------- ------------------- -------------------
1 2005-03-09 19:25:17 2005-03-09 19:23:39

根据查询结果,SNAPTIME$$的值刷新时刻的系统SYSDATE。

下面修改系统时间为10日。

SQL> insert into test values (2);

已创建1 行。

SQL> commit;

提交完成。

SQL> exec dbms_mview.refresh('mv_test_yangtingkun')

PL/SQL 过程已成功完成。

SQL> select id, to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') now_time,
2 to_char(snaptime$$, 'yyyy-mm-dd hh24:mi:ss') snaptime$$ from mlog$_test
3 where i

VMWare与Virtual PC比较

d = 2;

ID NOW_TIME SNAPTIME$$
---------- ------------------- -------------------
2 2005-03-10 19:30:56 2005-03-10 19:30:22

当时间向后调时http://www.arbdev.com/,SNAPTIME$$中的值仍然和系统时间保持一致。

下面修改系统时间为8日。

SQL> insert into test values (3);

已创建1 行。

SQL> commit;

提交完成。

SQL> exec dbms_mview.refresh('mv_test_yangtingkun')

PL/SQL 过程已成功完成。

SQL> select id, to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') now_time,
2 to_char(snaptime$$, 'yyyy-mm-dd hh24:mi:ss') snaptime$$ from mlog$_test
3 where id = 3;

ID NOW_TIME SNAPTIME$$
---------- ------------------- -------------------
3 2005-03-08 19:32:33 2005-03-10 19:30:23

可以看出,这回SNAPTIME$$的时间并没有跟随SYSDATE的变化,仍然是10日。

SQL> select id, to_char(snaptime$$, 'yyyy-mm-dd hh24:mi:ss') snaptime$$ from mlog$_test;

ID SNAPTIME$$
---------- -------------------
1 2005-03-09 19:23:39
2 2005-03-10 19:30:22
3 2005-03-10 19:30:23

通过这个方式,可以清楚的看到,系统时间小于SNAPTIME$$上次刷新时间时,本次时间为上次刷新时间加1秒。

SQL> select name, to_char(mview_last_refresh_time, 'yyyy-mm-dd hh24:mi:ss')
2 from user_base_table_mviews a, user_registered_mviews b
3 where a.mview_id = b.mview_id;

NAME TO_CHAR(MVIEW_LAST_
------------------------------ -------------------
MV_TEST_CABCCOM 2005-03-09 19:20:48
MV_TEST_YANGTINGKUN 2005-03-10 19:30:23

SQL> conn test/[email protected]
已连接。
SQL> exec dbms_mview.refresh('mv_test_cabccom')

PL/SQL 过程已成功完成。

SQL> commit;

提交完成。

SQL> select mview_name, to_char(last_refresh_date, 'yyyy-mm-dd hh24:mi:ss') last_time
2 from user_mviews where mview_name ='MV_TEST_CABCCOM';

MVIEW_NAME LAST_TIME
------------------------------ -------------------
MV_TEST_CABCCOM 2005-03-09 19:28:32

SQL> conn yangtk/yangtk@test
已连接。
SQL> select name, to_char(mview_last_refresh_time, 'yyyy-mm-dd hh24:mi:ss')
2 from user_base_table_mviews a, user_registered_mviews b
3 where a.mview_id = b.mview_id;

NAME TO_CHAR(MVIEW_LAST_
------------------------------ -------------------
MV_TEST_YANGTINGKUN 2005-03-10 19:30:23
MV_TEST_CABCCOM 2005-03-10 19:30:24

SQL> select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') now_time from dual;

NOW_TIME
-------------------
2005-03-08

你可能感兴趣的:(Oracle)