2024年3月15日发(作者:)
1,
在目标机上建立Oracle DB Link:
--在本地(目标机器)如下文件加入代码,连接到目标数据库上面
1.1,在network/admin/文件中加入源库的连接信息,
如:
AAA_10.5.1.3=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.5.1.3)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = AAA)
)
)
说明: 10.5.1.3:源库ip
AAA_10.5.1.3:创建的实例名(服务名)
1,2,在
目标机器上用sqlplus user/pwd登录:目标机器(本地)的用户名和密码,不是
源库机器的用户名和密码。
1.3,在本地机器(目标库)上用如下命令建立DB Link:
create public database link AAA_LINK connect to user identified by pwd using 'AA
A_10.5.1.3';
命令说明:
AAA_LINK:dblink的名称
user:源库的用户名
pwd :源库的密码
AAA_10.5.1.3:配置的实例名(服务名)
说明:CREATE PUBLIC DATABASE LINK
数据库链接名
CONNECT TO
用户名
IDENTIFIED
BY
密码
USING ‘
本地配置的数据的实例名
’;
如果建立成功,会提示:
Database link created.
1.4--测试使用链接的数据库(表名@dblink名称)
select * from FA_CARD@ AAA_LINK;
1.5创建一个测试表:在目标机器和原机器上都创建
create table dblink_test
(
user_id NUMBER,
user_name VARCHAR2(100)
);
--
在其中增加一条记录:
insert into dblink_test (user_id, user_name)
values (1, '钟德荣');
4, 使用如下脚本,即可同步数据表:
2.1 将源库的数据插入到目标库
方法一、
truncate table dblink_test;--
删除目标库的相应表数据
--
插入目标机器数据,来源于源库的数据
insert into dblink_test
select * from _test@KNG_LINK; --#
这里是指向要同步的来源表
,
表
名必须是
<
表所有者(源库的用户)
>.<
表名(源库的表)
>@
commit;
方法二、
merge into dblink_test b using dblink_test@KNG_LINK c on
(_ID=_ID)
--
如果
pk
(主键)值是相同则将目标库
c
将对应表的数据更新到源库
b
的对应表中
when matched then update set _NAME=_NAME
--
如果
pk
(主键)值不一至,则将目标表中的数据整条插入到源表中
when not matched then
insert values (_ID,_NAME);
--
记得
merge
后必须
commit,
否则更改未能提交
commit;
可以将以上语句作为sql脚本,然后写一个类似2.2的bat命令来作为任务执行
2.2 将目标库的数据插入或者更新到源库
--
从目标库
c
将对应表的数据插入到源库
b
的对应表中
方法一
insert into _test@KNG_LINK
select * from dblink_test;
方法二
merge into dblink_test@KNG_LINK b using dblink_test c on
(_ID=_ID)
--
如果
pk
(主键)值是相同则将目标库
c
将对应表的数据更新到源库
b
的对应表中
when matched then update set _NAME=_NAME
--
如果
pk
(主键)值不一至,则将目标表中的数据整条插入到源表中
when not matched then
insert values (_ID,_NAME);
--
记得
merge
后必须
commit,
否则更改未能提交
commit;
将以上脚本写入
中,然后建立文件,双击运行文件,那么系
统会自动将
目标库
c
将对应表的数据插入到源库
b
的对应表中,
可以将
作为任务定期执行(也可以按照3创建存储过程和任务来做)
如下图所示
如下图所示
5, 实现数据同步
方式一、通过2所描述的方式实现数据库数据同步(已测试)
方法二、创建存储过程和任务(待测试)
--创建一个存储过程
create procedure proc_sjtb
as
begin
delete from swdx_gzryxx where is_tb='1';
insert into swdx_gzryxx(gzrybh,mc,jgdm,phone,is_tb)select
distinct(_dm),_mc,_swjg_dm,_zgy,'1' from
dxpt_sjtb@mydblink t;
delete from gdzc_jg where is_tb='1';
insert into gdzc_jg(jg_dm,jg_mc,is_tb)select
distinct(_swjg_dm),_swjg_mc,'1' from dxpt_sjtb@mydblink t;
delete from swdx_nsrxx where is_tb='1';
insert into swdx_nsrxx(nsrsbh,nsrmc,jgdm,zgydm,is_tb)select
,,_swjg_dm,_dm,'1' from dxpt_sjtb@mydblink
t;
insert into swdx_nsrphone(nsrsbh,lbbh,tel) select
,'001',_NSR_CW from dxpt_sjtb@mydblink t;
insert into swdx_nsrphone(nsrsbh,lbbh,tel) select
,'002',_NSR_FR from dxpt_sjtb@mydblink t;
insert into swdx_nsrphone(nsrsbh,lbbh,tel) select
,'003',_NSR_QT from dxpt_sjtb@mydblink t;
delete from xt_czy where is_tb='1';
insert into xt_czy(czy_id, czy_mc, jg_code, czy_lxdh,
is_zgy,is_tb,is_jgczy,CZY_YXBZ) select distinct (_dm),
_mc, _swjg_dm, _zgy,'1','1','0','Y' from
dxpt_sjtb@mydblink t;
insert into xt_czy(czy_id, czy_mc, jg_code,
is_zgy,is_tb,is_jgczy,CZY_YXBZ) select
distinct(_swjg_dm),_swjg_mc,_swjg_dm,'0','1','1','Y'
from dxpt_sjtb@mydblink t;
end;
--创建任务(每分钟执行一次)
DECLARE X NUMBER;
BEGIN
_
(job => X
,what => 'proc_sjtb;'
,next_date => to_date('09-12-2008 00:00:00','dd/mm/yyyy
hh24:mi:ss')
,interval => 'TRUNC(sysdate) + 1 +2 / (24)'
);
END;
--执行任务
--RUN(参数)是我们建立任务的时候自动生成的,指定任务号方可启动任务和删除任务
begin
_(25);
end;
--删除任务
begin
_(23);
end;
方法三、创建触发器实现实时同步(测试通过)
--KNG_LINK
数据链名称
--cztbd
源数据库的用户名
--cztbd
源数据库的密码
--KNG ORACLE SID
实例名
(
源库
)
--1
、在源数据库上,创建要同步表的快照日志(不是很确定是否是在源库建立这个快照日志)
--DBLINK_TEST
:源库表,
LOG
:快照名称
,
不虚伪
log
不能修改,否则不能创建成功
Create snapshot LOG on DBLINK_TEST;
--2
、在目标数据库上创建快照
(
被同步(源)数据库服务必须启动
) DB_LINK_KZ
:快照名称
Create snapshot DB_LINK_KZ as select * from DBLINK_TEST@KNG_LINK;
--3
、设置刷新快照时间:如下写法为每隔一分钟刷新一次
Alter snapshot DB_LINK_KZ refresh fast Start with sysdate next
sysdate+1/1440;
---
删除快照的方法
drop snapshot DB_LINK_KZ;
DROP MATERIALIZED VIEW DB_LINK_KZ;
---
手动刷新快照
begin
dbms_h('DB_LINK_KZ');
end;
---
查看快照最后一次刷新时间
SELECT NAME,LAST_REFRESH FROM ALL_SNAPSHOT_REFRESH_TIMES;
---
查看快照下次执行时间
select last_date,next_date,what from user_jobs order by next_date;
--4
、创建触发器
:
在目标库创建未通过,
创建用于同步本地表与远程表(源数据库)数据的触发器由于创建快照后,快照在目标数据库表
现为会创建一个数据表DB_LINK_KZ,此表根据上一步骤设置的快照刷新时间自动与源数据库的
表user同步,要想实现两个数据库的真正同步,只需针对DB_LINK_KZ表创建一个触发器即可
解决,即通过触发器实现往目的数据库的指定数据表中插入数据,实现本地数据与目的数据库表
的数据同步。
写法一:(双向同步,源库表变化,则目标库表变化,目标库表变化,
则源库表变化)
说明:
如果你想双向同步,请在源数据库中执行和目标库一样的操作
(即:建立dblink,建立快照,快照刷新等),并在双方都创建以下触
发器
CREATE OR REPLACE TRIGGER TRI_KNG_LINK
AFTER DELETE OR INSERT OR UPDATE
ON DB_LINK__user
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
declare
tmp_id number(10):=-1;
flag number(3):=0;
begin
dbms__line('begin');
if inserting then
for p in(select user_id from DBLINK_TEST where
user_id=:_id)--DBLINK_TEST
:目标库表
loop
tmp_id:=_id;
end loop;
dbms__line(tmp_id||'===------------');
if (tmp_id=-1) then
insert into DBLINK_TEST(user_id,user_name)
values(:_id,:_name);
end if;
end if;
if updating then
dbms__line('updated');
for p in(select user_name from DBLINK_TEST where
user_id=:_id)
loop
if (_name!=:_name) then
update DBLINK_TEST set user_name=:_name where
user_id=:_id;
end if;
end loop;
end if;
if deleting then
dbms__line('deleted');
delete from DBLINK_TEST where user_id=:_id;
end if;
dbms__line('end');
end TRI_KNG_LINK;
--为防止双向同步触发器死循环,所以要在触发器中增加一些判断,阻止死循环.
问题描述:
1、测试发现,在目标库的DB_LINK_KZ表中数据变化了,则目标库的表DB_LINK数据也跟
着变化,但是源库的表DB_LINK数据变化,目标库的表DB_LINK数据没有着变化
2、同时再次测试发现:使用手动快照刷新之后,目标库的DB_LINK_KZ表中数据跟着源库
的表DB_LINK数据变化,目标库的表DB_LINK数据也跟着变化(这里实现是因为有触发器)
最终解决此问题:原来是快照刷新时间问题,快照没有刷新所以才造成了最终功能没有实
现,非常郁闷!!!!!!!!!
写法二:(单向同步,只在目标库进行更新等操作)
create or replace trigger TRI_test_user_AFR
after insert or update or delete on DB_LINK_KZ
for each row
begin
if deleting then
delete from DBLINK_TEST where user_id=:_id;
end if;
if inserting then
insert into DBLINK_TEST (user_id,user_name)
values(:_id,:_name);
end if;
if updating then
update DBLINK_TEST set user_name=:_name where
user_id=:_id;--记住:更新肯定是主键一致才更新
end if;
end TRI_test_user_AFR;
6, 下面再补充三点:
1、 创建DB_Link时,"tns_xj_to_bj"是指服务器端文件中所定义的环境
名,但在企业中,并没有几个人有权限查看这个文件中的内容。
解决办法:将‘tns_xj_to_bj’改写成客户端文件中对应的实际连接
串。如:
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.111)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = test)
)
)
注意:此处“(SERVER = DEDICATED)”可有可无,并没什么影响。
2、查看所有DBLink可采用以下两种方式
SQL1:select owner,object_name from dba_objects where
object_type='DATABASE LINK';
SQL2:select * from all_db_links;
但唵更偏向用SLQ2。No Reason!呵呵!
3、删除DB_Link
drop database link ;
其中database不能更改,为你创
建的DB_Link值(采用SQL2),当然需要用创建该DB_Link的用户登录才能成功删除!
7, 整个创建过程总结如下
5、1 dblink总结
--
创建
dblink
:在
ufgov/ufgov
登录
plsql
,然后之下下列脚本
create database link KNG_LINK
connect to catbd identified by catbd
using 'KNG_192.168.1.103';
--
查询
dblink
:
(表名@dblink名称):查询的是源库的表数据
select * from FA_CARD@KNG_LINK;
--
删除
dblink
drop public database link KNG_LINK;
--
返回数据库的
GLOBAL_NAME
SELECT * FROM GLOBAL_NAME;
--
查看远程数据库是否支持高级复制功能:
value=true
为支持
select * from v$option where PARAMETER='Advanced replication';
--4
、查询已经建立的远程连接名:
select owner,object_name from dba_objects where object_type='DATABASE
LINK';
--5
删除
dblink
:
DROP PUBLIC DATABASE LINK KNG_LINK。
如果创建全局dblink,必须使用systm或sys用户,在database前加public。
5.2 快照总结
1,ORACLE的快照刷新方式refresh有三种:
fast 快速刷新,用snapshot log,只更新时间段变动部分
complete 完全刷新,运行SQL语句
force 自动判断刷新,介于fast和complete之间
快照技术提供给我们三种刷新机制,分别是:
1) Complete 完全刷新机制,即对表的所有数据进行刷新,如果表的数据量十分庞大的,此法
会消耗相当的时间;
2) Fast 快速刷新,即只对数据增量进行刷新;
3) Force 强制刷新,首先判断是否能用快速刷新机制,如不行则用完全刷新机制。
2,若在数据库B上创建快速刷新,则要在数据库A上创建快照日志对象,否则
没这个必要,即第4步。
总结呈词:快照所实现的功能就是同步源库表和目标库表中的数据,而触发
器实现的是当前库的表与表之间的操作。


发布评论