1.复制原理
目前,USDP升级采用的是高级复制中的只读快照复制(只读物化视图复制),首先在主节点上建立物化视图日志,以备快速刷新。然后,在目标节点建立物化视图与刷新组,定时刷新主节点上变化的数据。数据刷新如果是目标节点向主节点主动获取的方式称为pull方式,除此之外,数据刷新是从主节点发起向目标节点推进的方式称为push方式。我们采用的是pull方式。 需要明确几个概念
1. 物化视图日志
通过以下语句创建
-- 创建物化视图日志
CREATE MATERIALIZED VIEW LOG ON master.t_fulltonelib
TABLESPACE RING WITH PRIMARY KEY;
通过以下语句删除
-- 删除物化视图日志
DROP MATERIALIZED VIEW LOG ON master.t_fulltonelib;
在创建物化视图日志的时候可以选择记录PK、OID或者ROWID,那么,物化视图就会记录发生变化的记录对应的PK、OID或者ROWID。我们一般采用PK,所以,在主表上必须要存在主键。可以查看MLOG$_master_name来查看主表上的物化视图日志。
在MLOG$_master_name的列中包含了一下的信息:
主表的主键PK SNAPTIME$$ 快照时间,这个时间比较特殊在以下的说明中会详细解释
DMLTYPE$$ DML操作类型, D 删除,U 更新,I 添加
OLD_NEW$$ 数据以前的状态,O 旧的,U 更新,N 新的
CHANGE_VECTOR$$ 处理队列的内部标示。
2. 物化视图通过以下语句创建
--创建物化视图
CREATE MATERIALIZED VIEW site.t_fulltonelib_MV
REFRESH FAST AS select * from master.t_fulltonelib;
通过以下语句删除
--清除同步节点上的物化视图
drop MATERIALIZED VIEW site.t_fulltonelib_mv;
说明:物化视图就是主表的一个快照,它分为3个部分 基表 存放具体的数据
视图 基于基表的对外表现形式
索引 在物化视图节点至少会为物化视图的主键创建一个索引,这个索引基于主节
点上主表的主键,命名为I_SNAP$_materializedview_name
刷新方式分为3种:
快速刷新 根据物化视图日志刷新变化的数据
完全刷新 先将物化视图清空,然后从主表上“完全拷贝”
强制刷新 先进行快速刷新,如果快速刷新失败,在进行完全刷新 刷新的语句为:
--快速刷新
BEGIN
DBMS_MVIEW.REFRESH ('t_fulltonelib_mv', 'f');
END;
--完全刷新函数
BEGIN
DBMS_MVIEW.REFRESH ('t_fulltonelib_mv', 'c');
END;
3. 刷新组
通过以下语句创建
--建立刷新组
BEGIN
DBMS_REFRESH.MAKE( name => 'RTEST01',
list => 't_fulltonelib_mv,t_userinfo_mv', next_date => sysdate, interval => 'sysdate + 0.5' );
END;
通过以下语句删除
--清除同步节点上的刷新组 BEGIN
DBMS_REFRESH.DESTROY(name => 'RTEST01');
END;
说明:刷新组通过建立一个job一次刷新多个物化视图。可以设定下次运行的时间和时
间间隔。可以通过以下语句来修改刷新组的刷新时间间隔。
--改变刷新时间
BEGIN
DBMS_REFRESH.CHANGE ( name => 'RTEST01', next_date => sysdate,
interval => 'sysdate + 10/86400' );
END;
4. 系统日志视图(sys用户或有系统日志访问权限的用户)
检查主节点上的系统日志
select t.mowner, t.master, t.snapid,
to_char(t.snaptime, 'yyyy-mm-dd hh24:mi:ss') time from slog$ t;
说明:当更新了slog$的快照时间才会清空物化视图日志的内容。
--更新slog$
update sys.slog$ set snaptime = :1 where snapid = :2 and mowner = :3 and master = :4
--得到快照时间
select snaptime from sys.slog$ where master = :2 and mowner = :1 order by snaptime
--清空物化视图日志
delete from "MASTER"."MLOG$_T_FULLTONELIB" where snaptime$$ <= :1
由于更新slog$是在快速刷新之后,所以,可以根据slog$的快照时间来检测同步是否正常。假设我们设置同步的时间是10秒,如果slog$的快照时间过10几秒发生一次变化,说明同步正常,如果slog$的快照时间一直不变化,说明同步可能出问题了。
注意:如果不是正常删除物化视图,而是直接drop快照节点,此时,slog$是不会被删除对应的记录的,从而导致物化视图日志不断的增加,此时,根据snapid调用DBMS_MVIEW.PURGE_LOG清空slog$。如下:
--清除主节点上的日志
BEGIN
DBMS_MVIEW.PURGE_LOG('t_fulltonelib', 1);
END;
之后,系统会自动清空物化视图日志。
注意:DBMS_MVIEW.PURGE_LOG 移除在slog$和mlog中最近最少刷新物化视图的行。第2个参数表示移除多少行,假设在slog$最近最少刷新的有3行,最近最少刷新时间分别为 a 2005-10-10 09:30:15, b 2005-10-10 10:31:10, c 2005-10-10 10:31:12,那么执行DBMS_MVIEW.PURGE_LOG('t_fulltonelib', 1)之后,会清空slog$中的记录a,而b和c是不会清空的。补充说明,在slog$中清空之后,对应的mlog也会清除相应的记录。
2.搭建同步环境
由于条件所限,我们在本机上搭建同步环境,以及以下的实验都是在本机进行模拟的。
创建主节点用户master和目标节点用户site
使用USDP脚本在本机上建立两个用户,分别为master和site.
我们选定两张表进行试验,分别为t_fulltonelib和t_userinfo。
创建主节点上的物化视图日志
--创建视图日志
CREATE MATERIALIZED VIEW LOG ON master.t_fulltonelib TABLESPACE RING
WITH PRIMARY KEY;
--创建视图日志
CREATE MATERIALIZED VIEW LOG ON master.t_userinfo
TABLESPACE RING
WITH PRIMARY KEY;
此时,生成了mlog$_t_fulltonelib和mlog$_t_userinfo。
删除目标节点上的用于同步的两张表t_fulltonelib和t_userinfo --drop table
drop table site.t_fulltonelib; drop table site.t_userinfo;
在目标节点上创建物化视图
--创建物化视图
CREATE MATERIALIZED VIEW site.t_fulltonelib_MV
REFRESH FAST AS select * from master.t_fulltonelib;
--创建物化视图
CREATE MATERIALIZED VIEW site.t_userinfo_MV
REFRESH FAST AS select * from master.t_userinfo;
在目标节点上创建刷新组
--建立刷新组
BEGIN
DBMS_REFRESH.MAKE( name => 'RTEST01',
list => 't_fulltonelib_mv,t_userinfo_mv', next_date => sysdate, interval => 'sysdate + 0.5' );
END;
Commit;
此时,slog$添加了t_fulltonelib和t_userinfo的注册信息。
在目标节点上刷新物化视图
--刷新
BEGIN
DBMS_MVIEW.REFRESH ('t_fulltonelib_mv');
END;
BEGIN
DBMS_MVIEW.REFRESH ('t_userinfo_mv');
END;
在目标节点上创建物化视图的索引 此步省略
在目标节点上创建物化视图的同义词
--建同义词
create or replace synonym t_fulltonelib for t_fulltonelib_mv;
create or replace synonym t_userinfo for t_userinfo_mv;
在目标节点上改变刷新组的刷新时间 --改变刷新时间
BEGIN
DBMS_REFRESH.CHANGE ( name => 'RTEST01', next_date => sysdate,
interval => 'sysdate + 10/86400' );
END;
在目标节点上检查job是否生成 select * from user_jobs;
如果job已经生成,此时同步环境就搭建好了。
在目标节点上手动运行一下job BEGIN
DBMS_JOB.run(1); END;
3.清除同步环境
清除同步环境与搭建同步环境正好相反,先从目标节点开始。
清除目标节点上的刷新组 --清除同步节点上的刷新组
BEGIN
DBMS_REFRESH.DESTROY(name => 'RTEST01');
END;
commit;
清除目标节点上的同义词
--清除同步节点上的同义词
drop synonym site.t_fulltonelib; drop synonym site.t_userinfo;
清除目标节点上的物化视图 --清除同步节点上的物化视图
drop MATERIALIZED VIEW site.t_fulltonelib_mv; drop MATERIALIZED VIEW site.t_userinfo_mv;
清除主节点上的物化视图日志 --清除主节点上的物化视图日志
drop MATERIALIZED VIEW LOG on t_fulltonelib; drop MATERIALIZED VIEW LOG on t_userinfo;
清除主节点上的系统日志
--清除主节点上的日志
BEGIN
DBMS_MVIEW.PURGE_LOG('t_fulltonelib', 1);
END;
--清除主节点上的日志
BEGIN
DBMS_MVIEW.PURGE_LOG('t_userinfo', 1);
END;
此时,同步环境就已经清除完毕。
实验1、在刷新的时间10s内无法将数据全部同步给目标节点。 操作:在十秒内不停的向主节点t_fulltonelib表中添加数据,测试是否会影响同步环境。 现象:
1. 添加10000条数据,可以正常同步。
2. 添加100000条数据,可以正常同步,但是job耗时较长。 3. 添加300000条数据,
实验2、直接drop目标节点,向主节点添加100条数据,检查物化视图日志。
实验3、导出site用户的数据,导入到其他节点,看是否会破坏同步。
实验4、搭建2个目标节点时,没有将第一个搭建成功的目标节点刷新时间改长。
实验5、在远程目标节点上,制造网络不通的现象,影响job的运行。