《Oracle 高级复制技术介绍及应用》
引言:Oracle 高级复制技术是Oracle最早提出的HA容灾解决方案,起源于Oracle 8i系统,至今在11G官方文档上依然可以找到高级复制说明文档。这个技术因为其古老我想大多数80后童靴只闻其声~未闻其形。在生产环境下可能更没有使用过。由于高级复制技术在当下已经属于非主流渐渐的退出了其历史舞台,逐步被Data Guard、Golden Gate、Streams等新技术所代替,导致其没落的原因是由于其本身机制问题,后面我们会介绍其原理和应用场景。虽说这种技术非常的原始,但可能还有一些老系统会继续使用着。一种技术我们需要知道其优点、应用场景、局限性、风险性,这样才能得心应手,有针对性的去使用,例如 原始的汇编语言现在几乎没有人在使用了,但由于其接近硬件的特点,在某些嵌入式系统中效率是最快的。所以说非主流技术我们也应该去了解一下,好的架构师就是需要具备在N种不同技术簇中,选择出最适合的。始终问自己:能不能压缩成本,能不能解决问题,能不能更易用。
《心得体会》
系统不同,架构不同,发现问题解决问题
好架构是系统演进出来的
保持简洁
易于扩展,监控,容错
一 高级复制技术应用架构
高级复制技术类型
(1)基于多主节点的复制(使用内部触发器)Master to Master
(2)基于物化视图的复制
(3)混合架构复制(既有多主节点又有物化视图,如上图所示)
二 说明高级复制和流复制在机制和应用场景上的异同点
刚才我们看到了高级复制的架构图,下面我们再来看一下流复制的架构图
基于redo流复制
基于归档流复制
实时流复制
流复制原理
原理:通过capture(捕获),propagation(传播),apply(应用)三个进程,将数据复制到目标数据库。三个步骤中间通过queue(oracle的advanced queue)进行连接,通过一系列的rule定义需要复制的数据,既可以是单点复制,也可以是多点复制。内部原理为capture进程从redo log中发掘dml和ddl操作,然后生成独特的LCR(Logical Change Record)数据单元并存于advanced queue中,propagation进程再将LCR queue传输到目标数据库,apply进程将接收的queue进行解析,并应用LCR中的DML和DDL操作,完成数据的复制。capture既可以在源库本地捕获,也可以在目标库捕获(downstream),如果是本地捕获,capture直接从redo log中读取信息;如果是downstream捕获,capture从redo log或archive log中捕获信息,中间的日志传输机制跟data guard一样。
从两张图中我们可知这两种技术的实现原理是不同的
高级复制原理
原理:当发生DML操作的时候,高级复制使用“内部触发器”捕获变化动作,并将这些操作封装在Remote Procedure Calls(RPCs就是一个存储过程)里,并借助Deferred Transaction Queue把RPCs推送到目标数据库,目标数据库利用“内部触发器”执行推送过来的RPCs(存储过程代码)从而实现了数据的复制。
高级复制优缺点汇总-免费
(1)需要稳定的网络环境,当网络因故障中断时,会出现丢包现象,从而丢失数据。
(2)适用于数据量小的场景,由于使用的是内部触发器原理,会消耗大量系统资源,当数据量很大的时候,会处理不过来。
(3)传输的速度较高,因为高级复制是基于事务触发的,当操作完之后马上触发->传递->应用
(4)高级复制不支持DDL语句复制,如果想执行DDL操作,先需要suspend复制组(承担高级复制的单位叫复制组),此时复制表只能查询不可执行任何DML语句,执行想要的DDL语句,然后重新generate复制支持,最后将复制组恢复到应用状态。当你不小心直接执行了DDL语句后会破坏掉复制环境,这时需将该表移出复制环境->删除->重新创建或从其他节点复制过来。
(5)基于分布式事务,当事务一开始复制就开始了,当事务出现问题复制也会出现问题,当事务回滚复制也会回滚。由于与事务紧密相关,可能会出现阻塞、争用、锁定现象,对用户操作影响较大。
当出现死锁现象时,我们可以broken掉对应的job作业
如果还不行,可以alter system kill session终止死锁会话
如果再不行,就需要利用v$lock查出类型为’RQ’的分布式死锁,再利用sid从v$process、v$session、v$bgprocess等视图中查出系统后台进程,从操作系统层面杀掉后台进程。
在重新建立job和相关复制环境
(6)Master to Master提供节点冗余,负载均衡的复制方式
所有节点关系是对等的,数据是对等的,当其中一个Master不可用时,可以直接切换到其他Master
负载均衡,例如有三个Master相互复制,用户1&2&3可以分别连接这三个Master主节点,实现负载均衡
常用于容灾场景
(7)支持同步和异步复制
同步:可以实时推送,操作后立马触发->复制->应用,因为复制的表上就建立了trigger和package。
异步:可以设置定时job(后台进程控制),定时、批量的复制数据,使用Deferred Transaction Queue实现。
(8)事务和依赖
高级复制自动处理事务的依赖关系,如果B事务访问A事务,并且A事务有更新,称作B事务对A事务有依赖
高级复制自动解决数据的约束关系
高级复制根据分布式事务方式,解决事务的一致性问题,比GG、Streams对事务的控制力更强,对用户操作参与更多,我们应该尽量把用户操作和数据复制分离开来,不要混淆在一起,提高系统的稳定性、健壮性。
(9)基于物化视图的高级复制
对网络质量要求不高,由于非实时传递,因此可以中断
定时、批量的复制数据,直接利用解析物化视图日志的方式复制数据
原理图
流复制优缺点汇总-免费
(1)也需要稳定的网络环境,如果网络中断,流复制就会失败
(2)Oracle自己的后台进程使用log miner工具从redo log或archive log中挖掘DML和DDL操作,对系统资源影响较小,streams是基于日志的分析,高级复制是基于触发器原理
(3)传输的速度会慢一些,因为日志挖掘本身就慢,再转换成SQL语句,应用SQL语句。我自己测试3秒钟延迟
(4)流复制支持DDL语句复制,采用DDL LCRs方式来记录DDL操作的改变
(5)流复制按照SCN号顺序捕获->传递->应用,只有redo数据写入log中才被挖掘,效率没有高级复制快
(6)用户操作和数据复制分离开来,数据复制过程中不会对用户操作有影响,增强了系统的稳定性、易用性
(7)流复制和高级复制都使用了高级队列来传输信息
(8)流复制也是Oracle HA技术之一,常用于容灾场景
三 演示针对某个表使用高级复制进行数据同步(Master to Master 内部触发器机制)
版本info
OS Version:Oracle Linux Release 6 Update 4 for x86_64 (64 Bit)
Oracle Version:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
linux.x64_11gR2_database_1of2.zip + linux.x64_11gR2_database_2of2.zip
Virtualbox Version:4.2.16
作者 info
User:leonarding 刘盛
Date:2013.09.12
Blog:www.leonarding.com
Site:China-beijing
总体架构图
高级复制
1.准备工作
检查初始化参数,source和destination节点都需要检查,区分一下名字,好理解哪个是源端,哪个是目标端
Source库
SYS@leo1> select * from global_name;
GLOBAL_NAME
--------------------------------------------------------------------------------
LEO1
Destination库
SYS@leo2> select * from global_name;
GLOBAL_NAME
--------------------------------------------------------------------------------
LEO2
确认global_name是否为ture,高级复制要求global_names=true
SYS@leo1> show parameter global_name
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
global_names boolean FALSE
SYS@leo1> alter system set global_names=true;
System altered.
SYS@leo1> show parameter global_name
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
global_names boolean TRUE
确认job_queue_processes>0,oracle11g 默认是1000
alter system set job_queue_processes=1000; 可以通过这条语句修改
SYS@leo1> show parameter job_queue_processes
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
job_queue_processes integer 1000
SYS@leo1> show parameter db_domain
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_domain string
高级复制技术要求global_name必须带域名,因此leo1后需要加后缀,什么后缀都可以
源端
SYS@leo1> alter database rename global_name to leo1.com;
Database altered.
SYS@leo1> select * from global_name;
GLOBAL_NAME
--------------------------------------------------------------------------------
LEO1.COM
目标端
SYS@leo2> alter database rename global_name to leo2.com;
Database altered.
SYS@leo2> select * from global_name;
GLOBAL_NAME
--------------------------------------------------------------------------------
LEO2.COM
2.配置tnsnames.ora文件
根据实际情况修改ip地址和service_name服务名,port一般都使用默认值1521
SYS@leo1> show parameter service_names
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
service_names string leo1
[oracle@leonarding2 admin]$ vim tnsnames.ora
leo1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.102)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = leo1)
)
)
leo2 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.103)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = leo2)
)
)
启动监听并tnsping测试连接字符串的连通性,两个节点都要测试成功
[oracle@leonarding2 admin]$ lsnrctl status
LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 12-SEP-2013 19:24:08
Copyright (c) 1991, 2009, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=source)(PORT=1521)))
TNS-12541: TNS:no listener
TNS-12560: TNS:protocol adapter error
TNS-00511: No listener
Linux Error: 111: Connection refused
[oracle@leonarding2 admin]$ lsnrctl start
LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 12-SEP-2013 19:25:46
Copyright (c) 1991, 2009, Oracle. All rights reserved.
TNS-01106: Listener using listener name LISTENER has already been started
[oracle@leonarding2 admin]$ lsnrctl status
LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 12-SEP-2013 19:25:50
Copyright (c) 1991, 2009, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=source)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 11.2.0.1.0 - Production
Start Date 12-SEP-2013 19:24:11
Uptime 0 days 0 hr. 1 min. 38 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/product/11.2.0/db_1/network/admin/listener.ora
Listener Log File /u01/app/oracle/diag/tnslsnr/leonarding2/listener/alert/log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=source)(PORT=1521)))
Services Summary...
Service "leo1" has 1 instance(s).
Instance "leo1", status READY, has 1 handler(s) for this service...
Service "leo1XDB" has 1 instance(s).
Instance "leo1", status READY, has 1 handler(s) for this service...
The command completed successfully
[oracle@leonarding2 admin]$ tnsping leo1
TNS Ping Utility for Linux: Version 11.2.0.1.0 - Production on 12-SEP-2013 19:26:00
Copyright (c) 1997, 2009, Oracle. All rights reserved.
Used parameter files:
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.102)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = leo1)))
OK (0 msec)
[oracle@leonarding2 admin]$ tnsping leo2
TNS Ping Utility for Linux: Version 11.2.0.1.0 - Production on 12-SEP-2013 19:29:54
Copyright (c) 1997, 2009, Oracle. All rights reserved.
Used parameter files:
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.103)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = leo2)))
OK (10 msec)
3.创建高级复制专属用户repadmin和数据库业务用户ar
每个用户都要有自己独立的表空间,源端和目标端都要创建
create tablespace repadmin datafile '/u01/app/oracle/oradata/leo1/repadmin_01.dbf' size 50M autoextend off;
create tablespace repadmin datafile '/u01/app/oracle/oradata/leo2/repadmin_01.dbf' size 50M autoextend off;
SYS@leo1> create user repadmin identified by oracle default tablespace repadmin;
User created.
SYS@leo1> grant dba to repadmin;
Grant succeeded.
执行存储过程
SYS@leo1> execute dbms_repcat_admin.grant_admin_any_schema('repadmin'); 注册管理者
PL/SQL procedure successfully completed.
SYS@leo1> execute dbms_defer_sys.register_propagator('repadmin'); 注册传播者
PL/SQL procedure successfully completed.
这里都使用了一个repadmin用户,也可以分别建立用户
说明:repadmin用户是高级复制环境的管理员,使用它可以建立复制组(承担高级复制任务的单位),加入复制对象,启动复制组等任务,为了操作方便我们给予了DBA权限。
创建数据库业务用户ar,源端和目标端都需要创建
create tablespace ar datafile '/u01/app/oracle/oradata/leo1/ar_01.dbf' size 50M autoextend off;
create tablespace ar datafile '/u01/app/oracle/oradata/leo2/ar_01.dbf' size 50M autoextend off;
SYS@leo1> create user ar identified by oracle default tablespace ar;
User created.
SYS@leo1> grant connect,resource to ar;
Grant succeeded.
说明:ar用户只是用来创建一些业务表,不负责高级复制的管理,不需要太高的权限
4.创建业务表
源端
SYS@leo1> conn ar/oracle
Connected.
AR@leo1> create table t (x int primary key);
Table created.
目标端
SYS@leo2> conn ar/oracle
Connected.
AR@leo2> create table t (x int primary key);
Table create
说明:源端和目标端表结构必须一致,才能正常复制。
我们的复制思路:从主节点leo1复制到另一个主节点leo2上,针对t表使用高级复制进行数据同步。
5.创建到目标端dblink
使用repadmin用户创建dblink,还有如果你设置了global_name,那么dblink名字必须和global_name一致
源端
AR@leo1> conn repadmin/oracle
Connected.
REPADMIN@leo1> create database link leo2.com connect to repadmin identified by oracle using 'leo2';
Database link created.
已经创建成功
REPADMIN@leo1> select db_link from dba_db_links;
DB_LINK
--------------------------------------------------------------------------------
LEO2.COM
远程测试
REPADMIN@leo1> select * from [email protected];
GLOBAL_NAME
--------------------------------------------------------------------------------
LEO2.COM
REPADMIN@leo1> select name from [email protected];
NAME
---------
LEO2
本地测试
REPADMIN@leo1> select name from v$database;
NAME
---------
LEO1
说明dblink生效了,当你设置了db_domain参数后global_name=name了。
6.源端创建Master复制组(承担高级复制任务的单位)
Oracle使用dbms_repcat包实现高级复制功能
REPADMIN@leo1> execute dbms_repcat.create_master_repgroup('rep');
PL/SQL procedure successfully completed.
查看复制组
REPADMIN@leo1> select gname,master,status from dba_repgroup where gname='REP';
GNAME M STATUS
-----------------------------------------------------
REP Y QUIESCED
说明:rep复制组已经创建完毕,当前状态quiesced静止的,还没有启动。一个任务由一个复制组实现。
7.加入复制对象(我们对谁进行复制就把谁加入进来)
加入master复制的对象
REPADMIN@leo1>execute dbms_repcat.create_master_repobject(sname=>'ar',oname=>'t',type=>'table',use_existing_object=>true,gname=>'rep',copy_rows=>false);
PL/SQL procedure successfully completed.
sname=>'ar' 复制对象的schema
oname=>'t' 复制对象的名字
type=>'table' 复制对象的类型
gname=>'rep' 复制对象加入到哪个复制组
use_existing_object=>true 可以使用已经创建的对象
copy_rows=>false 不拷贝行
REPADMIN@leo1> select sname,oname,gname,status from dba_repobject where gname='REP';
SNAME ONAME GNAME STATUS
------------------------------ ---------------------------------------------------------- ------------------------------
AR T REP VALID
说明:从dba_repobject数据字典中我们可以查询到已经把t表加入到rep复制组了,状态为valid。
8.对复制对象启动复制支持(就是在t表上生成内部触发器、存储过程、基表)
REPADMIN@leo1> execute dbms_repcat.generate_replication_support('ar','t','table');
PL/SQL procedure successfully completed.
REPADMIN@leo1> select sname,oname,gname,status from dba_repobject where gname='REP';
SNAME ONAME GNAME STATUS
------------------------------ ------------------------------ ------------------------------ ----------
AR T REP VALID
AR T$RP REP VALID
AR T$RP REP VALID
说明:把生成的T$RP存储过程也加入到rep复制组中了。
9.添加目标复制节点(你要把t表往哪个目标数据库上送)
源端,使用repadmin用户操作
REPADMIN@leo1> execute
dbms_repcat.add_master_database(gname=>'rep',master=>'leo2.com',use_existing_objects=>true,copy_rows=>false,propagation_mode=>'synchronous');
说明:把leo2.com数据库的dblink添加到rep复制组中,告诉rep复制组目标数据库就是我
gname=>'rep' 复制组名
master=>'leo2.com' 目标数据库dblink,由于global_name=true,dblink名和数据库名必须一致,oracle强制
propagation_mode=>'synchronous' 传送方式“同步”,实时性高
PL/SQL procedure successfully completed.
REPADMIN@leo1> select gname,dblink,masterdef,master from dba_repsites where gname='REP';
GNAME DBLINK MASTERDEF MASTER
------------------------------ ---------------------------------------------------------------------------------
REP LEO1.COM 源库 Y 发送主节点 Y
REP LEO2.COM 目标库 N 接收主节点 Y
目标端也应该可以查出
REPADMIN@leo2> select gname,dblink,masterdef,master from dba_repsites where gname='REP';
GNAME DBLINK MASTERDEF MASTER
------------------------------ -------------------------------------------------------------------------------------------------------------------------------- - -
REP LEO1.COM Y Y
REP LEO2.COM N Y
检查源端和目标端t表内容,应该都没有数据
源端
AR@leo1> select * from t;
no rows selected
目标端
AR@leo2> select * from t;
no rows selected
10.启动复制组rep(就可以实现高级复制了)
REPADMIN@leo1> execute dbms_repcat.resume_master_activity('rep',true);
PL/SQL procedure successfully completed.
说明:到此高级复制配置完毕,可以进行测试了
11.source->复制->destination
源端
AR@leo1> insert into t values(1);
insert into t values(1)
*
ERROR at line 1:
ORA-04067: not executed, stored procedure "AR.T$RP" does not exist 说明目标端t表上没有生成对应的存储过程
ORA-01085: preceding errors in deferred rpc to "AR.T$RP.REP_INSERT"
ORA-02063: preceding 2 lines from LEO2
检查目标端数据库告警日志
ORA-12012: error on auto execute of job 1
ORA-06550: line 1, column 8:
PLS-00352: Unable to access another database 'LEO1.COM' 不能访问源库LEO1.COM
ORA-06550: line 1, column 8:
PLS-00201: identifier '[email protected]' must be declared 必须声明到源库dblink
ORA-06550: line 1, column 8:
PL/SQL: Statement ignored
ORA-06550: line 1, column 7:
PLS-00352: Unable to access another database 'LEO1.COM'
ORA-06550: line 1, column 7:
PLS-00201: identifier '[email protected]' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
ORA-06512: at "SYS.DBMS_REPCAT_MAS", line 864
解决方法
目标端创建到源端dblink,因为两端有信息交互,必须相通
REPADMIN@leo2> create database link leo1.com connect to repadmin identified by oracle using 'leo1';
Database link created.
必须重启复制组rep
REPADMIN@leo1> execute dbms_repcat.suspend_master_activity('rep'); 暂停
PL/SQL procedure successfully completed.
REPADMIN@leo1> execute dbms_repcat.resume_master_activity('rep',true); 重启
PL/SQL procedure successfully completed.
直到源端和目标端的t表上都生成内部触发器、存储过程、基表才能正常复制
REPADMIN@leo1> select sname,oname,gname,status from dba_repobject where gname='REP';
SNAME ONAME GNAME STATUS
------------------------------ ------------------------------ ------------------------------ ----------
AR T REP VALID
AR T$RP REP VALID
AR T$RP REP VALID
参考官方文档地址:Database Advanced Replication Management API Reference书中的DBMS_REPCAT部分
目标端,当目标库t表上有这些东西时就可以正常复制了
REPADMIN@leo2> select sname,oname,gname,status from dba_repobject where gname='REP';
SNAME ONAME GNAME STATUS
------------------------------ ------------------------------ ------------------------------ ----------
AR T REP VALID
AR T$RP REP VALID
AR T$RP REP VALID
再次测试
源库,插入两条记录,当提交之后才会复制到目标库
AR@leo1> insert into t values(1);
1 row created.
AR@leo1> select * from t;
X
----------
1
AR@leo1> insert into t values(2);
1 row created.
AR@leo1> select * from t;
X
----------
1
2
AR@leo1> commit;
Commit complete.
目标库
AR@leo2> select * from t;
X
----------
1
2
源端,更新操作,提交之后才会传到目标库
AR@leo1> update t set x=10 where x=1;
1 row updated.
AR@leo1> update t set x=20 where x=2;
1 row updated.
AR@leo1> commit;
Commit complete.
目标端
AR@leo2> select * from t;
X
----------
10
20
DDL操作测试,上面我们说过了高级复制是不支持DDL操作的
源端
AR@leo1> truncate table t;
Table truncated.
AR@leo1> select * from t;
no rows selected
目标端并没有被清空,源端的DDL操作并不会影响到目标端的
AR@leo2> select * from t;
X
----------
10
20
自动解决数据的约束关系,GG、Streams就不会自动解决
源库
AR@leo1> insert into t values(10);
insert into t values(10)
*
ERROR at line 1:
ORA-00001: unique constraint (AR.SYS_C007046) violated 违反唯一约束
ORA-02063: preceding line from LEO2 来自于LEO2
说明:这个约束警告并不是源库t表上的有问题,而是当事务发生后高级复制会立刻自动检查两端的数据约束关系,
当发现目标库t表中有10这个值时,会立刻发出警告,这个警告说明的是目标库上违反了约束关系~全局约束。
AR@leo2> select * from t;
X
----------
10
20
全局约束:这是由分布式事务引起的,如果发现整个分布式环境中有约束冲突的话,就会告警。
我们插入30,就没有问题,感觉比GG、streams速度还要快
AR@leo1> insert into t values(30);
1 row created.
AR@leo1> commit;
Commit complete.
AR@leo2> select * from t;
X
----------
10
20
30
小结:这种基于内部触发器的高级复制是跟分布式事务紧密相连的,每个动作都是用户操作的一部分。这种模式非常适合容灾场景。缺点也是显而易见的,极易导致事务阻塞、争用、锁定,性能消耗较大,现在已经不是主流技术了。
advanced_replication,HA,基于触发器,队列
Leonarding
2013.09.13
北京&autumn
分享技术~成就梦想
Blog:www.leonarding.com