STREAM配置手札
1stream 介绍
Oracle从9i开始推出streams,用于提供灵活的复制和容灾解决方案。但是9i的streams配置相当的麻烦,少说也有十几个步骤,还容易出错。10gR2则将整个配置过程封装在几个简单的PL/SQL过程中,使得配置过程大大的简化。但是实际的配置步骤还是一样的,Oracle只是利用这些PL/SQL过程先生成对应的脚本,然后再执行脚本进行配置。这个过程可以全自动完成,也可以先将脚本生成到某个指定的目录,我们根据需要修改脚本,然后再执行脚本进行配置,这样就灵活又方便。
Streams的原理其实很简单,通过logmnr技术从oracle的log中解析出数据,然后传递到目标库并应用,从而将源库的数据复制到目标库。当然,复制可以是双向的,也可以是单向的。双向复制还需要考虑数据冲突的问题。而多源复制其实是双向复制的基础上衍生而来的。
整个的复制过程可以分成三个步骤:捕获(capture),传播(propagation)和应用(apply),利用高级队列(advance queue)来将这三个步骤的数据串起来,通过在步骤中定义不同的规则(rule)来控制需要复制的数据。复制可以基于全库,基于表空间,基于用户或者基于表,提供了相当大的灵活性。
捕获进程可以直接在源库捕获日志,也可以先将日志(归档日志或者联机日志)传递另外的库中进行捕获,这就是本地捕获(local capture)和异地捕获(downstream capture)。对于异地捕获,根据是传递归档日志还是联机日志,可以分为普通的异地捕获和实时异地捕获。日志的传递其实和DataGuard中是一样的机制。Oracle11g的streams还提供了同步捕获,这里暂时不涉及了。
描述一下复制的简单过程如下:
首先捕获进程从日志解析出数据,封装在一个个的逻辑改变记录(LCR:logical change record)中,将这些lcr压进捕获队列中,然后传播进程从捕获队列取得数据压进应用队列中,最后应用进程从应用队列取得LCR并应用到目标库中。LCR可以分为row LCR(DML操作记录)和DDL LCR(DDL操作记录),所以streams复制可以支持DDL操作的复制。
Streams复制需要先进行一次初始化建立基线,然后在此基础上复制增量数据。对于全库的初始化,可以使用RMAN。表空间复制的初始化可以使用transport tablespace,而对于用户复制和表复制,则可以使用exp/imp或者expdb/impdp。
Streams配置和管理相关package
dbms_steams_adm
dbms_capture_adm
dbms_propagation_adm
dbms_apply_adm
dbms_rule_adm
Streams主要相关数据字典
dba_streams_administrator
dba_capture
dba_capture_parameters
dba_propagation
dba_registered_archived_log
dba_apply
dba_apply_confict_columns
dba_apply_dml_handlers
dba_apply_enqueue
dba_apply_error
dba_apply_execute
dba_apply_parameters
dba_apply_progress
dba_rules
dba_rule_sets
dba_rule_set_rules
V$STREAMS_CAPTURE
V$STREAMS_POOL_ADVICE
V$STREAMS_TRANSACTION
V$PROPAGATION_RECEIVER
V$PROPAGATION_SENDER
V$STREAMS_APPLY_COORDINATOR
V$STREAMS_APPLY_READER
V$STREAMS_APPLY_SERVER
更多streams数据字典,请参考这里。
Streams涉及到很多的概念,本文只是提到了其中很少一部分,要想深入的了解streams机制和实现,请参考Oracle的两本官方文档:
Streams Concepts and Administration
Streams Replication Administrator’s Guide
2 配置
简单说一下环境:oracle 11.2.0.2 linux 64bit
源库:10.2.2.20 sid:ccxgather/10.2.2.18 sid:demo18
目标库:10.2.2.16 sid:quality
2.1 检查系统参数
--检查以下参数,其实除第一个外其他在11g采用默认值即可
alter system set aq_tm_processes=2 scope=both;
alter system set global_names=true scope=both;
alter system set job_queue_processes=10 scope=both;
alter system set parallel_max_servers=20 scope=both;
alter system set undo_retention=3600 scope=both;
alter system set nls_date_format='YYYY-MM-DD HH24:MI:SS' scope=spfile;
alter system set streams_pool_size=25M scope=spfile;
--downstream不需要
alter system set utl_file_dir='*' scope=spfile;
--11.2默认为4
alter system set open_links=4 scope=spfile;
2.2 检查主键
在10.2.2.20(源库)
select t.table_name,c.index_name,c.constraint_type from
(select * From dba_tables where owner='owner1') t left join
(select * from dba_constraints where owner='owner1' and constraint_type='P') c
on t.table_name=c.table_name
where c.index_name is null
2.3创建streamadmin用户
在10.2.2.16上:
CREATE TABLESPACE streams_tbs DATAFILE '/data/quality/streams_tbs.dbf' SIZE 100M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
create user username identified by "Password" default tablespace streams_tbs;
grant dba to username;
begin
exec DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('stradmin');
end;
在10.2.2.20上:
CREATE TABLESPACE streams_tbs DATAFILE '/data/oradata/progather/streams_01.dbf' SIZE 100M
REUSE AUTOEXTEND ON next 100M MAXSIZE 8192M;
create user username identified by "password" default tablespace streams_tbs;
grant dba to username;
begin
exec DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('username');
end;
2.4 建立dblink
在10.2.2.20上
create database link quality connect to usernameidentified by pasword using '16';
--测试一下
select * from global_name@stream
在10.2.2.16上
create database link progathe connect to username identified by password using '20';
2.5 建立复制目录—异地捕获表级不需要
源库 10.2.2.18
create directory dir_source_01 as '/data/source/'
10.2.2.20
create directory stream_01 as '/data/oradata/progather/'
2.6 将日志传送至目标库
源库上执行
--追加尾日志
alter database add supplemental log data;
alter system set log_archive_config=’dg_config=(demo18,quality)’
alter system set log_archive_dest_2 ='service=quality arch noregister db_unique_name=quality';
说明:生成密码文件
orapwd
目标库上执行:
alter system set log_archive_config=’dg_config=(demo18,quality)’
2.7 执行dbms_streams_adm包中的maintain_*
2.7.1--建立表空间级复制
declare
v_ts dbms_streams_tablespace_adm.tablespace_set;
begin
v_ts(1) := 'tablespacesname';
dbms_streams_adm.maintain_tts(
tablespace_names => v_ts,
source_directory_object => 'stream_20',
destination_directory_object => 'stream_16',
source_database => 'stream20',
destination_database => 'stream16',
perform_actions => true,
include_ddl => true);
end;
- MAINTAIN_SIMPLE_TTS :单个表空间的复制
- MAINTAIN_TTS :多个表空间的复制
- PRE_INSTANTIATION_SETUP 和POST_INSTANTIATION_SETUP:多个表空间的复制
--检查是不否有自包含
SQL> exec sys.dbms_tts.transport_set_check('owner',true,true);
PL/SQL procedure successfully completed
SQL> select * from sys.transport_set_violations;
select * from dba_apply;
select * from dba_apply_error;
2.7.2 多表复制
先将表exp源库再imp到目标库
exp demo/demo@demo18 file=demo.dmp
imp demo/demo@quality file=demo.dmp
declare
v_tables dbms_utility.uncl_array;
begin
v_tables(1) := DEMO.BOND_ASE_PLAN';
dbms_streams_adm.maintain_tables(
table_names => v_tables,
source_directory_object => NULL,
destination_directory_object => NULL,
source_database => 'demo18',
destination_database => 'quality',
perform_actions => true,
bi_directional => false,
include_ddl => true,
instantiation => dbms_streams_adm.instantiation_table_network);
end;
/
说明:在源库执行maintain_tables时,目标库几乎什么都不用做,stream环境已经配置好啦,
如果想复制其它的表,只用再执行maintain_tables过程即可,其实他是封装了以前9i的步骤
.可以从DBA_RECOVERABLE_SCRIPT_BLOCKS查出详细步骤
2.7.3 shema级复制
BEGIN
DBMS_STREAMS_ADM.MAINTAIN_SCHEMAS(
schema_names =>'OWNER',
source_directory_object => 'DIR_SOURCE',
destination_directory_object => 'DIR_DEST',
source_database => 'DEMO18',
destination_database => 'QUALITY',
perform_actions => true,
dump_file_name => NULL,
log_file => NULL,
bi_directional => NULL,
include_ddl => true,
instantiation => DBMS_STREAMS_ADM.INSTANTIATION_SCHEMA);
END;
- DBMS_STREAMS_ADM.INSTANTIATION_SCHEMA :通过expdp/impdp初始化数据,并在目标端导入数据时执行实例化,默认情况下即是该值。
- DBMS_STREAMS_ADM.INSTANTIATION_SCHEMA_NETWORK :impdp直接通过网络传输数据而不生成dmp文件。在导入数据时执行实例化。
- DBMS_STREAMS_ADM.INSTANTIATION_NONE :不执行实例化,该属性值仅当perform_actions参数设置为false时有效。
不过这里有个很不可思议的事情,如果dump在imp过程中出错了,从字典视图取不到任何记录,只能看dump_dest目录下的dlg文件。至于怎么清除这个job,暂时没办法。
3相关错误
3.1错误字典
DBA_RECOVERABLE_SCRIPT:配置脚本概要信息
DBA_RECOVERABLE_SCRIPT_PARAMS:配置脚本参数
DBA_RECOVERABLE_SCRIPT_ERRORS:执行过程中的错误信息
DBA_RECOVERABLE_SCRIPT_BLOCKS:配置脚本的详细步骤
Eg:
执行一个表复制时报这个错:
ORA-23616: Failure in executing block 2 for script AE0FA65415C205D6E040007F010066A8 with
ORA-20099: SORRY,YOU CAN NOT EXECUTE THE COMMAND. PLEASE CONTACT THE DBA
ORA-06512: at "SYS.DBMS_RECO_SCRIPT_INVOK", line 139
--取出错误步骤
select * from dba_recoverable_script where script_id='AE0FA65415C205D6E040007F010066A8'
select * from dba_recoverable_script_blocks where script_id='AE0FA65415C205D6E040007F010066A8'
and block_num=1
--看错误详细信息
select * from dba_recoverable_script_errors where script_id='AE0FA65415C205D6E040007F010066A8'
and block_num=1
ORA-20099: SORRY,YOU CAN NOT EXECUTE THE COMMAND. PLEASE CONTACT THE DBA
ORA-06512: at "SYS.DBMS_RECO_SCRIPT_INVOK", line 139
ORA-06512: at "SYS.DBMS_STREAMS_RPC", line 485
3.2 重新执行
begin
dbms_streams_adm.recover_operation(
script_id => 'D74179203F11445D8F3F3F77C0749A1D',
operation_mode => 'FORWARD');
end;
/
3.3如果错误比较严重,无法再继续进行配置,那么可以将已经完成的步骤回滚掉
begin
dbms_streams_adm.recover_operation(
script_id => 'D74179203F11445D8F3F3F77C0749A1D',
operation_mode => 'ROLLBACK');
end;
/
3.4 清除stream配置
begin
dbms_streams_adm.recover_operation(
script_id => 'D74179203F11445D8F3F3F77C0749A1D',
operation_mode => 'PURGE');
end;
/
查询并停止正在捕捉
select capture_name,status from dba_capture;
停止
SQL> exec dbms_capture_adm.stop_capture('STREAM20$CAP');
查询并停止propagation进程
select propagation_name,status from dba_propagation;
SQL> exec dbms_propagation_adm.stop_propagation('PROPAGATION$_4');
exec dbms_propagation_adm.drop_propagation('PROPAGATION$_4');
查询删除queue
SQL> select * from dba_queues where owner='STRADMIN'
SQL> exec dbms_streams_adm.remove_queue('DEMO18$APPQ');
PL/SQL procedure successfully completed
SQL> exec dbms_streams_adm.remove_queue('AQ$_DEMO18$APPQT_E');
PL/SQL procedure successfully completed
查询apply进程:
SQL> select apply_name,queue_name from dba_apply;
APPLY_NAME QUEUE_NAME
------------------------------ ------------------------------
APPLY$_STREAM20_15 STREAM20$APPQ
exec dbms_apply_adm.stop_apply('APPLY$_STREAM20_15');
最后清除整个stream配置
exec dbms_streams_adm.remove_streams_configuration;
删除rule
SQL> exec dbms_rule_adm.drop_rule('BOND_ASE_PLAN12 ');
Drop ruleset
SQL> exec dbms_rule_adm.drop_rule_set('RULESET$_11');
3.5 scn不一致处理
select APPLY_NAME,LOCAL_TRANSACTION_ID,SOURCE_COMMIT_SCN,MESSAGE_NUMBER,ERROR_MESSAGE from dba_apply_error;
source_commit_scn:1205861453
26687 ORA-26687: no instantiation SCN provided for "DEMO"."BOND_ASE_PLAN" in source da
--继续执行
BEGIN
DBMS_APPLY_ADM.START_APPLY(apply_name => 'APPLY$_DEMO18_3');
END;
--源库执行
begin
DBMS_APPLY_ADM.set_table_instantiation_scn@quality(source_object_name => 'DEMO.BOND_ASE_PLAN',
source_database_name => 'DEMO18',
instantiation_scn => 1205861453);
end;
--目标库上执行
BEGIN
DBMS_APPLY_ADM.EXECUTE_ERROR(
local_transaction_id => '9.30.10856',
execute_as_user => FALSE,
user_procedure => NULL);
END;
3.6高级复制中的ORA-23318 /ORA-23308
如果先创建表而后使用了alter table add primary key()添加pk,那么到后来就会报出上述的错误,必须使用:
create table test (a number primary key);
或者
alter table test add constraint......的形式。