Oracle流复制技术

Oracle流复制是结合日志挖掘、队列等技术,实现多数据库、异构、远程等环境下数据同步的一种实现方式。主要被用于灵活的复制和容灾解决方案。


Oracle流复制相比较其他数据库同步方式,如Dataguard、Advanced Replication,流复制拥有以下几点显著的优势:

1、灵活的复制策略:可以分别针对数据库、模式、表等不同级别设定复制策略,相比Dataguard必须整个数据库复制而言,可以节省相当的资源。

2、高可用性:在异构环境下(不同的操作系统),Dataguard无法使用,流复制可以充分利用现有的设备与技术。

3、对网络条件的轻度依赖:流复制的传播是经过logmnr挖掘并包装的逻辑变更记录(LCRs),相比Dataguard传送archived redo log、Advanced Replication的mview log与mview刷新的方式,流复制对网络的需求降低了很多。

4、实时性:由监控进程负责实时监控用户操作反应在log当中的记录并传递给目标数据库进行接收,然后转换为实际的操作同步目标数据库,并可根据实际情况调整同步的间隔。

5、对主数据库性能的低影响:相对于其他复制方式,流复制基于对log物理文件进行分析等动作完成,只占用极少部分资源,并且无论流复制执行成功与否,都不会影响到主库的正常使用。


流复制中,源库必须设置为归档模式,如果是双向复制,则源库和目标库都要置于归档模式。


以下给出一个在生产环境中的具体例子来说明流复制技术的运用方法。这里的需求是主服务器数据库的一个名为CMES的模式,包括其表、索引、存储过程代码等对象结构和数据的变更都要求能同步到本地节点的数据库中。


一、搭建流复制环境


1、本地节点的流复制环境搭建


conn / as sysdba


修改实例参数

alter system set global_names=true;

alter system set aq_tm_processes=1;


创建streams表空间

create tablespace streams datafile 'd:\oradata\mes\streams01.dbf' size 200m;


logminer 的数据字典从system表空间转移到streams表空间

execute dbms_logmnr_d.set_tablespace('streams');


创建strmadmin用户并授权

create user strmadmin identified by strmadmin default tablespace streams quota unlimited on streams;

grant connect, resource, dba, aq_administrator_role to strmadmin;

begin

    dbms_streams_auth.grant_admin_privilege(grantee          => 'strmadmin',

                                            grant_privileges => true);

end;

/


tnsnames.ora中添加服务名,指向主服务器端

mes_0 =

  (DESCRIPTION =

    (ADDRESS_LIST =

      (ADDRESS = (PROTOCOL = TCP)(HOST = ora11g-1)(PORT = 1521))

    )

    (CONNECT_DATA =

      (SERVICE_NAME = mes)

    )

  )


创建指向主服务器端的数据库链接

create public database link dl_mes_0 connect to system identified by mesHz2 using 'mes_0';


测试通过数据库链接可以访问到对方主机

select host_name from v$instance@dl_mes_0;


HOST_NAME

----------------------------------------------------------------

ORA11G-1


创建与数据库链接访问同名的global_name

第一个本地节点可命名为dl_mes_1,第二个本地节点可命令为dl_mes_2,以此类推

alter database rename global_name to dl_mes_1;


创建流队列

conn strmadmin/strmadmin

exec dbms_streams_adm.set_up_queue();


创建应用进程

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_rules(schema_name     => 'cmes',

                                      streams_type    => 'apply',

                                      streams_name    => 'apply_streams',

                                      queue_name      => 'strmadmin.streams_queue',

                                      include_dml     => true,

                                      include_ddl     => true,

                                      source_database => 'dl_mes_0',

                                      inclusion_rule  => true);

end;

/


2、主服务器端的流复制环境搭建


conn / as sysdba


开启补充日志

alter database add supplemental log data;


修改实例参数

alter system set global_names=true;

alter system set aq_tm_processes=1;

alter system set open_links=10 scope=spfile;

alter system set open_links_per_instance=10 scope=spfile;


创建streams表空间

create tablespace streams datafile 'd:\oradata\mes\streams01.dbf' size 200m;


logminer的数据字典从系统表空间转移到streams表空间

execute dbms_logmnr_d.set_tablespace('streams');


创建strmadmin用户并授权

create user strmadmin identified by strmadmin default tablespace streams quota unlimited on streams;

grant connect, resource, dba, aq_administrator_role to strmadmin;

begin

    dbms_streams_auth.grant_admin_privilege(grantee          => 'strmadmin',

                                            grant_privileges => true);

end;

/


tnsnames.ora中添加指向各个本地节点的网络服务名

第一个本地节点可命名为mes_1,第二个本地节点可命令为mes_2,以此类推,各节点计算机名对应为oraxe11g-1oraxe11g-2

mes_1 =

  (DESCRIPTION =

    (ADDRESS_LIST =

      (ADDRESS = (PROTOCOL = TCP)(HOST = oraxe11g-1)(PORT = 1521))

    )

    (CONNECT_DATA =

      (SERVICE_NAME = mes)

    )

  )


创建数据库链接

对应各个本地节点的网络服务名来创建,如dl_mes_1对应mes_1dl_mes_2对应mes_2

create public database link dl_mes_1 connect to system identified by mesHz2 using 'mes_1';


测试通过数据库链接dl_mes_1dl_mes_2等可以分别访问到各个节点

select host_name from v$instance@dl_mes_1;


HOST_NAME

----------------------------------------------------------------

ORAXE11G-1


创建与数据库链接访问同名的global_name

alter database rename global_name to dl_mes_0;


创建流队列

conn strmadmin/strmadmin

exec dbms_streams_adm.set_up_queue();


创建捕获进程

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_rules(schema_name    => 'cmes',

                                      streams_type   => 'capture',

                                      streams_name   => 'capture_streams',

                                      queue_name     => 'strmadmin.streams_queue',

                                      include_dml    => true,

                                      include_ddl    => true,

                                      inclusion_rule => true);

end;

/


创建传播进程

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_propagation_rules(schema_name            => 'cmes',

                                                  streams_name           => 'main_to_node1',

                                                  source_queue_name      => 'strmadmin.streams_queue',

                                                  destination_queue_name => 'strmadmin.streams_queue@dl_mes_1',

                                                  include_dml            => true,

                                                  include_ddl            => true,

                                                  source_database        => 'dl_mes_0',

                                                  inclusion_rule         => true,

                                                  queue_to_queue         => true);

end;

/


当需要创建多个传播进程向不同节点发布时,需要指定不同的stream_namedestination_queue_name,如以下创建指向第二个本地节点的传播进程

conn strmadmin/strmadmin

begin

    dbms_streams_adm.add_schema_propagation_rules(schema_name            => 'cmes',

                                                  streams_name           => 'main_to_node2',

                                                  source_queue_name      => 'strmadmin.streams_queue',

                                                  destination_queue_name => 'strmadmin.streams_queue@dl_mes_2',

                                                  include_dml            => true,

                                                  include_ddl            => true,

                                                  source_database        => 'dl_mes_0',

                                                  inclusion_rule         => true,

                                                  queue_to_queue         => true);

end;

/


3、实例化本地节点


根据具体业务,利用数据泵进行导入。这里具体业务是需要创建几个自己的表空间和用户模式,并从主服务器上导入模式数据到本地。


conn / as sysdba


创建表空间

create tablespace cmes datafile 'd:\oradata\mes\cmes01.dbf' size 100m;

create tablespace rmes datafile 'd:\oradata\mes\rmes01.dbf' size 2g;

create tablespace indx datafile 'd:\oradata\mes\indx01.dbf' size 2g;

create tablespace hmes datafile 'd:\oradata\mes\hmes01.dbf' size 2g;


创建RMESBOSCHABS用户并授权

create user rmes identified by rmes default tablespace rmes;

create user bosch identified by huizhong default tablespace rmes;

create user abs identified by huizhong default tablespace rmes;

grant connect,resource to rmes,bosch,abs;


导入主服务器端的CMES模式基础数据

$impdp strmadmin/strmadmin network_link=dl_mes_0 schemas=cmes


导入主服务器端的RMESBOSCHABS模式元数据

$impdp strmadmin/strmadmin network_link=dl_mes_0 schemas=rmes,bosch,abs content=metadata_only


编译无效对象

@?/rdbms/admin/utlrp


4、启动流复制进程


本地节点启动应用进程

conn strmadmin/strmadmin

exec dbms_apply_adm.start_apply('apply_streams');


主服务器端启动捕获进程

conn strmadmin/strmadmin

exec dbms_capture_adm.start_capture('capture_streams');


检查主服务器端警告日志,确认日志捕获的启动

Fri Apr 14 16:47:04 2017

LOGMINER: Begin mining logfile for session 1 thread 1 sequence 40, E:\ARCHIVELOG\MES\ARC_78AE6A4D_1_941117583_40.LOG

Fri Apr 14 16:47:05 2017

LOGMINER: End mining logfile: E:\ARCHIVELOG\MES\ARC_78AE6A4D_1_941117583_40.LOG

Fri Apr 14 16:47:05 2017

LOGMINER: Begin mining logfile for session 1 thread 1 sequence 41, D:\ORADATA\MES\REDO02.LOG

Fri Apr 14 16:47:14 2017

LOGMINER: End mining logfile: D:\ORADATA\MES\REDO02.LOG

Fri Apr 14 16:47:14 2017

LOGMINER: Begin mining logfile for session 1 thread 1 sequence 42, D:\ORADATA\MES\REDO03.LOG


检查本地节点警告日志,确认日志应用的启动

Fri Apr 14 16:46:41 2017

Streams APPLY AP01 for APPLY_STREAMS started with pid=24, OS id=3144

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS02 with pid=31 OS id=1768

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS03 with pid=32 OS id=2484

Fri Apr 14 16:46:42 2017

Streams Apply Reader for APPLY_STREAMS started AS01 with pid=29 OS id=4040

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS04 with pid=35 OS id=756

Fri Apr 14 16:46:42 2017

Streams Apply Server for APPLY_STREAMS started AS05 with pid=36 OS id=740


5、流复制功能验证


测试主服务器端数据库CMES模式的更新,是否能够自动同步到本地节点,包括DMLDDL操作。如未能同步,则检查主服务器端和本地节点的警告日志信息,排查出错原因。


表数据更新

select * from cmes.c_emp_t;

update cmes.c_emp_t t set t.emp_password = '111111' where t.emp_no = 'TEST';

commit;


增加表

create table cmes.c_emp1_t as select * from cmes.c_emp_t;

select * from cmes.c_emp1_t;


修改表结构

alter table cmes.c_emp1_t add remark varchar2(20);

update cmes.c_emp1_t t set t.remark = 'test' where t.emp_no = 'TEST';

commit;

desc cmes.c_emp1_t;


增加索引

create index cmes.idx_emp1_remark on cmes.c_emp1_t(remark) tablespace indx;

select table_name, index_name, index_type, status, tablespace_name from dba_indexes where owner='CMES' and table_name='C_EMP1_T';


删除索引

drop index cmes.idx_emp1_remark;

select table_name, index_name, index_type, status, tablespace_name from dba_indexes where owner='CMES' and table_name='C_EMP1_T';


删除表

drop table cmes.c_emp1_t purge;

select * from cmes.c_emp1_t;


新增存储过程

create or replace procedure cmes.my_test(res out varchar2) as

begin

    res := 'OK';

end;

/


更新存储过程

create or replace procedure cmes.my_test(res out varchar2) as

begin

    res := 'NOK';

end;

/


删除存储过程

drop procedure cmes.my_test;


6、建立流复制心跳


为监视流复制的工作状态,在主服务器上创建心跳表

create table cmes.streams_hb(hb_name varchar2(20), hb_time varchar2(20)) tablespace cmes;


插入数据

insert into cmes.streams_hb values('dl_mes_0', to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'));

commit;


创建调度作业,设置为每分钟更新一次心跳时间

conn strmadmin/strmadmin

begin

    dbms_scheduler.create_job(job_name        => 'strmadmin.job_streams_hb',

                              job_type        => 'plsql_block',

                              job_action      => 'update cmes.streams_hb set hb_time = to_char(sysdate, ''yyyy-mm-dd hh24:mi:ss'') where hb_name = ''dl_mes_0'';',

                              start_date      => sysdate,

                              repeat_interval => 'freq = minutely; interval = 1',

                              enabled         => true,

                              auto_drop       => false);

end;

/


观察本地节点的心跳表数据是否按心跳时间同步更新

select * from cmes.streams_hb;


HB_NAME              HB_TIME

-------------------- --------------------

dl_mes_0             2017-05-09 12:19:47


二、针对表级别的配置说明


如果流复制定义在表级别,则几个进程的创建可采用如下形式。


主服务器端创建表级别的传播进程

begin

    dbms_streams_adm.add_table_propagation_rules(table_name             => 'scott.emp',

                                                 streams_name           => 'scott_emp_main_to_node1',

                                                 source_queue_name      => 'strmadmin.streams_queue',

                                                 destination_queue_name => 'strmadmin.streams_queue@dl_mes_1',

                                                 include_dml            => true,

                                                 include_ddl            => true,

                                                 source_database        => 'dl_mes_0',

                                                 inclusion_rule         => true,

                                                 queue_to_queue         => true);

end;

/


主服务器端创建表级别的捕获进程

begin

    dbms_streams_adm.add_table_rules(table_name     => 'scott.emp',

                                     streams_type   => 'capture',

                                     streams_name   => 'scott_emp_capture_streams',

                                     queue_name     => 'strmadmin.streams_queue',

                                     include_dml    => true,

                                     include_ddl    => true,

                                     inclusion_rule => true);

end;

/


本地节点创建表级别的应用进程

begin

    dbms_streams_adm.add_table_rules(table_name      => 'scott.emp',

                                     streams_type    => 'apply',

                                     streams_name    => 'scott_emp_apply_streams',

                                     queue_name      => 'strmadmin.streams_queue',

                                     include_dml     => true,

                                     include_ddl     => true,

                                     source_database => 'dl_mes_0',

                                     inclusion_rule  => true);

end;

/


本地节点的实例化

本地节点导入主服务器端的表

$impdp strmadmin/strmadmin network_link=dl_mes_0 schemas=scott include=table:"in('EMP')" table_exists_action=replace


三、流复制配置的删除


停止应用进程

conn strmadmin/strmadmin

exec dbms_apply_adm.stop_apply(apply_name => 'apply_streams');


删除应用进程

conn strmadmin/strmadmin

begin

  dbms_apply_adm.drop_apply(apply_name            => 'apply_streams',

                            drop_unused_rule_sets => true);

end;

/


如果删除应用进程时报错应用进程的错误队列必须为空,则需要先删除之前应用进程所有的错误信息,然后再执行删除进程的操作

conn strmadmin/strmadmin

select * from dba_apply_error;

exec dbms_apply_adm.delete_all_errors(apply_name=>'apply_streams');


停止捕获进程

conn strmadmin/strmadmin

begin

  dbms_capture_adm.stop_capture(capture_name => 'capture_streams',

                                force        => true);

end;

/


删除捕获进程

conn strmadmin/strmadmin

begin

  dbms_capture_adm.drop_capture(capture_name          => 'capture_streams',

                                drop_unused_rule_sets => true);

end;

/


停止传播进程

conn strmadmin/strmadmin

begin

  dbms_propagation_adm.stop_propagation(propagation_name => 'main_to_node1',

                                        force            => true);

end;

/


删除传播进程

conn strmadmin/strmadmin

begin

  dbms_propagation_adm.drop_propagation(propagation_name      => 'main_to_node1',

                                        drop_unused_rule_sets => true);

end;

/


删除主服务器端和本地节点的队列及队列表

conn strmadmin/strmadmin

begin

dbms_streams_adm.remove_queue(queue_name              => 'STREAMS_QUEUE',

                              cascade                 => true,

                              drop_unused_queue_table => true);

end;

/


删除流配置

conn strmadmin/strmadmin

exec dbms_streams_adm.remove_streams_configuration;


删除流用户

conn / as sysdba

drop user strmadmin cascade;


四、流复制的状态查询


查看创建的流队列和队列表

select owner, name, queue_table, queue_type from dba_queues where owner = 'STRMADMIN';


OWNER      NAME                           QUEUE_TABLE                    QUEUE_TYPE

---------- ------------------------------ ------------------------------ --------------------

STRMADMIN  AQ$_STREAMS_QUEUE_TABLE_E      STREAMS_QUEUE_TABLE            EXCEPTION_QUEUE

STRMADMIN  STREAMS_QUEUE                  STREAMS_QUEUE_TABLE            NORMAL_QUEUE


查看流队列表信息

select owner, queue_table, object_type from dba_queue_tables where owner = 'STRMADMIN';


OWNER      QUEUE_TABLE                    OBJECT_TYPE

---------- ------------------------------ --------------------------

STRMADMIN  STREAMS_QUEUE_TABLE            SYS.ANYDATA


查看传播进程信息

col destination_dblink for a30

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

------------------------------ ------------------------------ ------------------------------ ------------------------------ ----------

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       ENABLED

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED


查看捕获进程信息

select capture_name, queue_name, start_scn, status, capture_type from dba_capture;


CAPTURE_NAME                   QUEUE_NAME                      START_SCN STATUS     CAPTURE_TY

------------------------------ ------------------------------ ---------- ---------- ----------

CAPTURE_STREAMS                STREAMS_QUEUE                     6156463 ENABLED    LOCAL


查看应用进程信息

select apply_name,queue_name,status from dba_apply;


APPLY_NAME                     QUEUE_NAME                     STATUS

------------------------------ ------------------------------ --------

APPLY_STREAMS                  STREAMS_QUEUE                  ENABLED


五、补充说明


1、可以基于Database级别或Table级别启用追加日志(Supplemental Log)

alter database add supplemental log data;


在建立根据Schema粒度进行复制的Oracle Stream环境中,如果确认Schema下所有Table都有合理的主键(Primary Key),则可不需要启用追加日志。


2、根据需要可修改传播进程的休眠时间,如改为0,表示实时传播

begin

    dbms_aqadm.alter_propagation_schedule(queue_name        => 'streams_queue',

                                          destination       => 'dl_mes_1',

                                          destination_queue => 'streams_queue',

                                          latency           => 0);

end;

/


3、如果等了很长时间数据还没有复制过来,仔细检查capture/propagation/apply各进程的状态是否有异常。并可尝试修改以下隐含参数并重启

alter system set "_job_queue_interval"=1 scope=spfile;


4、如果本地节点长时间关闭或无法与主服务器端保持网络连接,可能导致主服务器端的传播进程状态变为disabled,此时即便恢复了连接,仍然不能保持正常的同步复制。这种情况可以尝试先停止主服务器端到本地节点的传播进程,然后重新启动传播进程,一般情况下问题都可以得到解决。


查询传播进程状态,发现到dl_mes_2的传播是disabled

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

------------------------------ ------------------------------ ------------------------------ ------------------------------ --------

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       DISABLED


停止该传播进程

begin

  dbms_propagation_adm.stop_propagation(propagation_name => 'main_to_node2',

                                        force            => true);

end;

/


此时该进程状态变为aborted

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

------------------------------ ------------------------------ ------------------------------ ------------------------------ --------

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       ABORTED


重启传播进程

exec dbms_propagation_adm.start_propagation(propagation_name => 'main_to_node2');


查看状态已恢复正常

select propagation_name, source_queue_name, destination_queue_name, destination_dblink, status from dba_propagation;


PROPAGATION_NAME               SOURCE_QUEUE_NAME              DESTINATION_QUEUE_NAME         DESTINATION_DBLINK             STATUS

------------------------------ ------------------------------ ------------------------------ ------------------------------ --------

MAIN_TO_NODE1                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_1                       ENABLED

MAIN_TO_NODE2                  STREAMS_QUEUE                  STREAMS_QUEUE                  DL_MES_2                       ENABLED


5、如果本地节点应用进程状态变为abort,可尝试以下操作


停止应用进程

exec dbms_apply_adm.stop_apply(apply_name => 'apply_streams');


查看应用进程的报错信息

select * from dba_apply_error;


在确认错误已排除后,删除错误信息

exec dbms_apply_adm.delete_all_errors(apply_name=>'apply_streams');


重启应用进程

exec dbms_apply_adm.start_apply('apply_streams');


再次检查应用进程状态是否已恢复为enabled

select apply_name,queue_name,status from dba_apply;


APPLY_NAME                     QUEUE_NAME                     STATUS

------------------------------ ------------------------------ ----------

APPLY_STREAMS                  STREAMS_QUEUE                  ENABLED

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28974745/viewspace-2137631/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28974745/viewspace-2137631/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值