1引言
Oracle Stream功能是为提高数据库的高可用性而设计的,在Oracle 9i及之前的版本这个功
能被称为Advance Replication。Oracle Stream利用高级队列技术,通过解析归档日志,将归档日志解析成DDL 及DML 语句,从而实现数据库之间的同步。这种技术可以将整个数据
库、数据库中的对象复制到另一数据库中,通过使用Stream 的技术,对归档日志的挖掘,
可以在对主系统没有任何压力的情况下,实现对数据库对象级甚至整个数据库的同步。
解析归档日志这种技术现在应用的比较广泛,Quest 公司的shareplex 软件及DSG 公司的
realsync 都是这样的产品,一些公司利用这样的产品做应用级的容灾。但shareplex 或是
realsync 都是十分昂贵的,因此你可以尝试用Stream 这个Oracle 提供的不用额外花钱的功能。Oracle Stream对生产库的影响是非常小的,从库可以是与主库不同的操作系统平台,你可以利用Oracle Stream复制几个从库,从库可用于查询、报表、容灾等不同的功能。本文不谈技术细节,只是以手把手的方式一步一步的带你把Stream 的环境搭建起来,细节内容可以查联机文档。
2 概述
主数据库:
操作系统:redhat-4
IP地址:192.168.1.180
数据库:Oracle 10.2.0.1.0
ORACLE_SID:ess
Global_name:ess
从数据库1:
操作系统:Red Hat Enterprise Linux AS release 4 (Nahant Update 2)
IP地址:192.168.1.181
数据库:Oracle 10.2.0.1.0
ORACLE_SID:hncenter
global_name:hncenter
从数据库2:
操作系统:redhat-5
IP地址:192.168.1.182
数据库:Oracle 10.2.0.1.0
ORACLE_SID:centerbase
global_name:centerbase
3 环境准备
3.1 设定初始化参数
使用 pfile的修改init<SID>.ora 文件,使用spfile的通过alter system命令修改spile文件。
主、从数据库分别执行如下的语句:
sqlplus / as sysdba
alter system set aq_tm_processes=1 scope=both;
alter system set global_names=true scope=both;
alter system set job_queue_processes=10 scope=both;
alter system set "_job_queue_interval"=1 scope=spfile;
alter system set TIMED_STATISTICS=true;
alter system set STATISTICS_LEVEL=TYPICAL;
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=300M scope=spfile;
alter system set utl_file_dir= '* ' scope=spfile;
alter system set open_links=4 scope=spfile;
执行完毕后重启数据库。
3.2 将主数据库置为归档模式
设置 log_archive_dest_1 到相应的位置;设定log_archive_start为TRUE,即启用自动归档功
能;设定log_archive_format指定归档日志的命令格式。
举例:
sqlplus / as sysdba
alter system set log_archive_dest_1='location=/u02/oradata/arch' scope=spfile;
--注意此步是当原系统没有设置归档路径的情况下
alter system set log_archive_start=TRUE scope=spfile;
alter system set log_archive_format='arch%t_%s_%r.arc' scope=spfile;
shutdown immediate;
startup mount;
alter database archivelog;
alter database open;
数据库置为归档模式后,可以按如下方式检验一下:
SQL> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /u02/oradata/arch
Oldest online log sequence 121
Next log sequence to archive 123
Current log sequence 123
观注标红的部分。
3.3 创建stream 管理用户
3.3.1 创建主环境stream管理用户
#以sysdba 身份登录
connect / as sysdba
#创建主环境的Stream专用表空间
create tablespace tbs_stream datafile '/u02/oradata/im/tbs_stream01.dbf'
size 100m autoextend on maxsize unlimited segment space management auto;
#将logminer 的数据字典从system表空间转移到新建的表空间,防止撑满system表空间
execute dbms_logmnr_d.set_tablespace('tbs_stream');
#创建Stream管理用户
create user strmadmin identified by strmadmin
default tablespace tbs_stream temporary tablespace temp;
#授权Stream管理用户
grant connect,resource,dba,aq_administrator_role to strmadmin;
begin
dbms_streams_auth.grant_admin_privilege(
grantee => 'strmadmin',
grant_privileges => true);
end;
/
3.3.2 创建从环境stream管理用户
#以sysdba 身份登录
connect / as sysdba
#创建Stream专用表空间
create tablespace tbs_stream datafile '/u02/oradata/im/tbs_stream01.dbf'
size 100m autoextend on maxsize unlimited segment space management auto;
#同样,将logminer 的数据字典从system 表空间转移到新建的表空间,防止撑满system 表
空间
execute dbms_logmnr_d.set_tablespace('tbs_stream');
#创建Stream管理用户
create user strmadmin identified by strmadmin
default tablespace tbs_stream temporary tablespace temp;
#授权Stream管理用户
grant connect,resource,dba,aq_administrator_role to strmadmin;
begin
dbms_streams_auth.grant_admin_privilege(
grantee => 'strmadmin',
grant_privileges => true);
end;
/
3.4 配置网络连接
3.4.1配置主环境tnsnames.ora
#主数据库(tnsnames.ora)中添加从数据库的配置。
HNCENTER =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.181)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = hncenter)
)
)
CENTERBASE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.182)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = centerbase)
)
)
3.4.2配置从环境tnsnames.ora
#从数据库1(tnsnames.ora)中添加主数据库的配置。
ESS =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.180)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = ess)
)
)
#从数据库2(tnsnames.ora)中添加主数据库的配置。
CENTERBASE =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.180)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = ess)
)
)
3.4.3网络连接配置检查
#主数据库与从数据库是否相通检查
sqlplus strmadmin/strmadmin@hncenter
SQL>
sqlplus strmadmin/strmadmin@centerbase
SQL>
#从数据库与主数据库是否相通检查
sqlplus strmadmin/strmadmin@ess
SQL>
#出现SQL>则表示登陆进了相应数据库,已经相通
3.5 启用追加日志
可以基于Database级别或Table级别,启用追加日志(Supplemental Log)。在建立根据Schema
粒度进行复制的Oracle Stream 环境中,如果确认Schema 下所有Table 都有合理的主键
(Primary Key),则不再需要启用追加日志。
#启用Database 追加日志
alter database add supplemental log data;
#启用Table追加日志
alter table add supplement log group log_group_name(table_column_name) always;
3.6 创建DBlink
根据Oracle 10gR2 Stream官方文档,针对主数据库建立的数据库链的名字必须和从数据库
的global_name相同。
如果需要修改global_name,
sqlplus / as sydba
alter system set global_names=true scope=both;
alter database rename global_name to xxx;
。
3.6.1创建主数据库数据库链
#以strmadmin身份,登录主数据库。
connect strmadmin/strmadmin
#与从数据库1建立数据库链
create database link hncenter connect to strmadmin identified by strmadmin using 'hncenter';
#与从数据库2建立数据库链
create database link centerbase connect to strmadmin identified by strmadmin using 'centerbase';
3.6.2创建从数据库数据库链
#以strmadmin身份,登录从数据库。
connect strmadmin/strmadmin
#建立数据库链
create database link ess connect to strmadmin identified by strmadmin using 'ess';
3.6.3数据库连接检查
#主数据库连接检查
connect strmadmin/strmadmin
select sysdate from dual@hncenter;
select sysdate from dual@centerbase;
#从数据库连接检查
connect strmadmin/strmadmin
select sysdate from dual@ess;
#如果返回的都是正常日期值,说明连接创建成功
3.7 创建流队列
3.7.1创建Master流队列
#以strmadmin身份,登录主数据库。
connect strmadmin/strmadmin
begin
dbms_streams_adm.set_up_queue(
queue_table => 'ess_queue_table',
queue_name => 'ess_queue');
end;
/
3.7.2创建Backup流队列
#以strmadmin身份,登录从数据库1。
connect strmadmin/strmadmin
begin
dbms_streams_adm.set_up_queue(
queue_table => 'hncenter_queue_table',
queue_name => 'hncenter_queue');
end;
/
#以strmadmin身份,登录从数据库2。
connect strmadmin/strmadmin
begin
dbms_streams_adm.set_up_queue(
queue_table => 'centerbase_queue_table',
queue_name => 'centerbase_queue');
end;
/
3.8 创建捕获进程
#以strmadmin身份,登录主数据库。提醒一下,本文档以im 用户做示例。
connect strmadmin/strmadmin
begin
dbms_streams_adm.add_schema_rules(
schema_name => 'im',
streams_type => 'capture',
streams_name => 'capture_ess',
queue_name => 'strmadmin.ess_queue',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => null,
inclusion_rule => true);
end;
/
3.9 实例化复制数据库
在主数据库环境中,exp导出主用户信息。
exp userid=system/zdsoft@ess file='/u02/oradata/dmp/im.dmp' object_consistent=y rows=y owner=im
导出操作如遇到“EXP-00056: ORACLE 错误...”的解决方法
执行@catmeta.sql,@catmetx.sql,@utlrp.sql 三个文件
--scp -P22 /u02/oradata/dmp/im.dmp root@192.168.1.181:/u02/oradata
--网络imp省略此步
--scp -P22 /u02/oradata/dmp/im.dmp root@192.168.1.182:/u02/oradata
--网络imp省略此步
如果从库的im 用户和表空间不存在,先在从库建立一个表空间和im 的空用户。
CREATE SMALLFILE TABLESPACE tbs_im DATAFILE
'/u02/oradata/im/tbs_im.dbf' SIZE 1024M AUTOEXTEND ON NEXT 1024M MAXSIZE 4096M
LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
CREATE USER im PROFILE "DEFAULT" IDENTIFIED BY zdsoft DEFAULT
TABLESPACE tbs_im TEMPORARY TABLESPACE temp ACCOUNT UNLOCK;
GRANT CREATE SESSION,CREATE TABLE,CONNECT,RESOURCE TO im;
然后导入主库用户文件(在主库端执行imp)
imp userid=system/zdsoft@hncenter file='/u02/oradata/dmp/im.dmp' ignore=y commit=y log='/u02/oradata/dmp/imp_hncenter.log' streams_instantiation=y fromuser=im touser=im
imp userid=system/zdsoft@centerbase file='/u02/oradata/dmp/im.dmp' ignore=y commit=y log='/u02/oradata/dmp/imp_centerbase.log' streams_instantiation=y fromuser=im touser=im
在Streams复制中,可以通过exp/imp方式进行数据初始化,也可以通过DBMS_APPLY_ADM来设置。
通常通过DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN来进行SCHEMA级别的设置:
直接设置SCN的方式进行实例化:
---获取源库互置用户的SCN,然后设置为目标库用户的SCN
主库执行:
connect strmadmin/strmadmin
DECLARE v_scn NUMBER;
BEGIN
--源库获取SCN
v_scn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
--从库1设置SCN
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@hncenter(
SOURCE_SCHEMA_NAME => 'im',
source_database_name => 'ess',
instantiation_scn => v_scn,
RECURSIVE => true );
--从库2设置SCN
DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@centerbase(
SOURCE_SCHEMA_NAME => 'im',
source_database_name => 'ess',
instantiation_scn => v_scn,
RECURSIVE => true );
END;
/
3.10 创建传播进程
#以strmadmin身份,登录主数据库。
connect strmadmin/strmadmin
begin
dbms_streams_adm.add_schema_propagation_rules(
schema_name => 'im',
streams_name => 'ess_to_hncenter',
source_queue_name => 'strmadmin.ess_queue',
destination_queue_name => 'strmadmin.hncenter_queue@hncenter',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'ess',
inclusion_rule => true);
end;
/
begin
dbms_streams_adm.add_schema_propagation_rules(
schema_name => 'im',
streams_name => 'ess_to_centerbase',
source_queue_name => 'strmadmin.ess_queue',
destination_queue_name => 'strmadmin.centerbase_queue@centerbase',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'ess',
inclusion_rule => true);
end;
/
#修改propagation休眠时间为0,表示实时传播LCR。
begin
dbms_aqadm.alter_propagation_schedule(
queue_name => 'ess_queue',
destination => 'hncenter',
latency => 0);
end;
/
begin
dbms_aqadm.alter_propagation_schedule(
queue_name => 'ess_queue',
destination => 'centerbase',
latency => 0);
end;
/
3.11 创建应用进程
#以strmadmin身份,登录从数据库。
connect strmadmin/strmadmin
begin
dbms_streams_adm.add_schema_rules(
schema_name => 'im',
streams_type => 'apply',
streams_name => 'apply_hncenter',
queue_name => 'strmadmin.hncenter_queue',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'ess',
inclusion_rule => true);
end;
/
connect strmadmin/strmadmin
begin
dbms_streams_adm.add_schema_rules(
schema_name => 'im',
streams_type => 'apply',
streams_name => 'apply_centerbase',
queue_name => 'strmadmin.centerbase_queue',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'ess',
inclusion_rule => true);
end;
/
3.12 启动STREAM
#以strmadmin身份,登录从数据库1,启动Apply进程
connect strmadmin/strmadmin
--为了使发生错误时,能让应用进程继续工作,可以做下面设置
begin
dbms_apply_adm.set_parameter(
apply_name => 'apply_hncenter',
parameter => 'disable_on_error',
value => 'n');
END;
/
--启动应用进程
begin
dbms_apply_adm.start_apply(
apply_name => 'apply_hncenter');
end;
/
#以strmadmin身份,登录从数据库2,启动Apply进程
connect strmadmin/strmadmin
--为了使发生错误时,能让应用进程继续工作,可以做下面设置
begin
dbms_apply_adm.set_parameter(
apply_name => 'apply_centerbase',
parameter => 'disable_on_error',
value => 'n');
END;
/
--启动应用进程
begin
dbms_apply_adm.start_apply(
apply_name => 'apply_centerbase');
end;
/
--以strmadmin身份,登录主数据库,启动传播进程(一般可省略此步,因为创建传播进程后就自动启动)
BEGIN
DBMS_PROPAGATION_ADM.START_PROPAGATION(
PROPAGATION_NAME=>'ess_to_hncenter');
DBMS_PROPAGATION_ADM.START_PROPAGATION(
PROPAGATION_NAME=>'ess_to_centerbase');
END;
/
#以strmadmin身份,登录主数据库,启动Capture进程
connect strmadmin/strmadmin
begin
dbms_capture_adm.start_capture(
capture_name => 'capture_ess');
end;
/
3.13 停止STREAM
--以strmadmin身份,登录主数据库,停止Capture进程
connect strmadmin/strmadmin
begin
dbms_capture_adm.stop_capture(
capture_name => 'capture_ess');
end;
/
--以strmadmin身份,登录主数据库,停止传播进程
connect strmadmin/strmadmin
BEGIN
DBMS_PROPAGATION_ADM.STOP_PROPAGATION(
PROPAGATION_NAME=>'ess_to_hncenter',
FORCE=>TRUE);
DBMS_PROPAGATION_ADM.STOP_PROPAGATION(
PROPAGATION_NAME=>'ess_to_centerbase',
FORCE=>TRUE);
END;
/
#以strmadmin身份,登录从数据库1,停止Apply进程
connect strmadmin/strmadmin
begin
dbms_apply_adm.stop_apply(
apply_name => 'apply_hncenter');
end;
/
#以strmadmin身份,登录从数据库2,停止Apply进程
connect strmadmin/strmadmin
begin
dbms_apply_adm.stop_apply(
apply_name => 'apply_centerbase');
end;
/
3.14 清除所有配置信息
要清楚 Stream配置信息,需要先执行3.13,停止Stream进程。
#以strmadmin身份,登录主数据库。
connect strmadmin/strmadmin
exec DBMS_STREAMS_ADM.remove_streams_configuration();
#以strmadmin身份,登录从数据库。
connect strmadmin/strmadmin
exec DBMS_STREAMS_ADM.remove_streams_configuration();
正常情况下,执行 DBMS_STREAMS_ADM.REMOVE_STREAMS_CONFIGURATION 会进行下列操作:
- 删除所有capture进程。
- 如果仍有表正准备初始化,则通过DBMS_CAPTURE_ADM.ABORT_TABLE_INSTANTIATION过程中止。
- 如果仍有schema正准备初始化,则通过DBMS_CAPTURE_ADM.ABORT_SCHEMA_INSTANTIATION过程中止。
- 如果数据库仍正准备初始化,则通过DBMS_CAPTURE_ADM.ABORT_GLOBAL_INSTANTIATION过程中止。
- 删除propagation进程(DBMS_AQADM包创建的propagation不会被删除),删除之前,传播任务将会被禁止。
- 禁止所有传播任务。
- 删除所有apply进程。如果apply进程存在应用错误,则在删除apply进程前会首先删除这些应用错误。
- 删除apply进程的DDL handlers,不过用于handlers的pl/sql过程不会被删除。
- 删除apply进程的message handlers,同样用于handlers的pl/sql过程不会被删除。
- 删除apply进程的precommit handlers,用于handlers的pl/sql过程不会被删除。
- 删除所有应用对象,schema的instantiation SCN和ignore SCN。
- 删除消息客户端
- 重置使用DBMS_STREAMS_ADM.SET_MESSAGE_NOTIFICATION设置的message notification specifications
- 删除DML handlers和error handlers,用于handlers的pl/sql过程不会被删除。
- 删除update conflict handlers。
- 删除apply tables的substitute key columns。
- 删除DBMS_STREAMS_ADM创建的规则集。但不会删除DBMS_RULE_ADM创建的规则集。
提示:
在执行删除capture/apply进程前会首先停止这些进程。 REMOVE_STREAMS_CONFIGURATION 过程可 重 复执行(不管是否执行成功) ,如果执行出错,可在解决造成错误的原因后重新执行该过程。
另外,有时候直接执行REMOVE_STREAMS_CONFIGURATION会报错,这个时候可以尝试通过DBMS_CAPTURE_ADM/DBMS_PROPAGATION_ADM/DBMS_APPLY_ADM手工停止并删除捕获/传播/应用进程,然后再执行REMOVE_STREAMS_CONFIGURATION过程。
4 测试场景
本文档建立了针对im用户的Stream 复制环境,如果没有特别声明,以下测试场景均以im
用户身份执行。
4.1 建一张表测试
主数据库
SQL> CREATE TABLE test_strm(id NUMBER(2) PRIMARY KEY,name VARCHAR2(50));
从数据库
SQL> desc test_strm
4.2 表中插入一行数据
主数据库
SQL> insert into test_strm values (1,'teststrm');
SQL> commit;
从数据库
SQL> select * from test_strm;
4.3 变更一下表的结构,添加一列
主数据库
SQL> ALTER TABLE test_strm ADD(creation_time DATE);
从数据库
SQL> desc test_strm
4.4 将表换一个表空间
主数据库
SQL> SELECT table_name,tablespace_name FROM user_tables
2 WHERE table_name='TEST_STRM';
SQL> ALTER TABLE test_strm MOVE TABLESPACE tbs_stream;
SQL> SELECT table_name,tablespace_name FROM user_tables
WHERE table_name='test_strm';
从数据库
SQL> SELECT table_name,tablespace_name FROM user_tables
WHERE table_name='TEST_STRM';
4.5 表上Name列建一索引
主数据库
SQL> CREATE INDEX idx_test_strm_name ON test_strm(name);
从数据库
SQL> SELECT table_name, index_name FROM user_indexes WHERE table_name = 'TEST_STRM';
4.6 Rebuild索引测试
主数据库
SQL> ALTER INDEX idx_test_strm_name REBUILD;
从数据库
SQL> SELECT table_name, index_name FROM user_indexesWHERE table_name = 'TEST_STRM';
4.7 索引换一个表空间测试
主数据库
SQL> ALTER INDEX idx_test_strm_name REBUILD TABLESPACE tbs_stream;
从数据库
SQL> SELECT table_name,index_name,tablespace_name FROM user_indexes
WHERE table_name = 'TEST_STRM';
4.8 删除索引测试
主数据库
SQL> DROP INDEX idx_test_strm_name;
从数据库
SQL> SELECT table_name,index_name,tablespace_name FROM user_indexes
WHERE table_name = 'TEST_STRM';
4.9 删除表测试
主数据库
SQL> DROP TABLE test_strm;
从数据库
SQL> DESC test_strm;
4.10 建一张带有LOB类型字段的表测试
主数据库
SQL> CREATE TABLE test_strm_clob(id NUMBER(2) PRIMARY KEY, memo CLOB);
从数据库
SQL> DESC test_strm_clob;
4.11 表中插入一行数据
主数据库
SQL> INSERT INTO test_strm_clob VALUES(1,'clob_test');
SQL> commit;
从数据库
SQL> SELECT * FROM test_strm_clob;
主数据库删除测试表(为了还原真实环境)
SQL> DROP TABLE test_strm_clob;
从数据库
SQL> DESC test_strm_clob;
4.12 创建Type测试
主数据库
SQL> CREATE or REPLACE TYPE test_strm_type;
从数据库
SQL> SELECT * FROM user_types WHERE type_name='TEST_STRM_TYPE';
4.13 删除Type测试
主数据库
SQL> DROP TYPE test_strm_type;
从数据库
SQL> SELECT * FROM user_types WHERE type_name='TEST_STRM_TYPE';
5 问题诊断
5.1 如何知道捕捉(Capture)进程是否运行正常?
以 strmadmin身份,登录主数据库,执行如下语句:
SQL> SELECT CAPTURE_NAME,QUEUE_NAME,RULE_SET_NAME,NEGATIVE_RULE_SET_NAME,STATUS
FROM DBA_CAPTURE;
结果显示如下:
CAPTURE_NAME QUEUE_NAME
------------------------------ ------------------------------
RULE_SET_NAME NEGATIVE_RULE_SET_NAME STATUS
------------------------------ ------------------------------ --------
CAPTURE_PROD PROD_QUEUE
RULESET$_14 ENABLED
ENABLED
如果STATUS状态是ENABLED,表示Capture进程运行正常;
如果STATUS状态是DISABLED,表示Capture进程处于停止状态,只需重新启动即可;
如果STATUS 状态是ABORTED,表示Capture 进程非正常停止,查询相应的
ERROR_NUMBER、ERROR_MESSAGE 列可以得到详细的信息;同时,Oracle会在跟
踪文件中记录该信息。
5.2 如何知道Captured LCR是否有传播GAP?
以 strmadmin身份,登录主数据库,执行如下语句:
SQL> SELECT CAPTURE_NAME, QUEUE_NAME, STATUS, CAPTURED_SCN,APPLIED_SCN FROM DBA_CAPTURE;
结果显示:
如果APPLIED_SCN 小于CAPTURED_SCN,则表示在主数据库一端,要么LCR 没有被
dequeue,要么Propagation进程尚未传播到从数据库一端。
5.3 如何知道Appy进程是否运行正常?
以 strmadmin身份,登录从数据库,执行如下语句:
SQL> SELECT apply_name, apply_captured, status FROM dba_apply;
结果显示如下:
APPLY_NAME APPLY_ STATUS
---------------------- ------ ----------------
APPLY_H10G YES ENABLED
如果STATUS状态是ENABLED,表示Apply进程运行正常;
如果STATUS状态是DISABLED,表示Apply进程处于停止状态,只需重新启动即可;
如果STATUS 状态是ABORTED,表示Apply 进程非正常停止,查询相应的
ERROR_NUMBER、ERROR_MESSAGE 列可以得到详细的信息;同时,可以查询
DBA_APPLY_ERROR视图,了解详细的Apply错误信息。
6 结篇
通过如上的测试可以看出stream的功能还是十分强大的,通过配置Oracle Stream可以更大
的提升数据库的可用性和安全性,如此一个好用且不用花费高昂额外费用的功能还是很值得
一用的。__
7 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
8流捕获进程——流(概念)
流的捕获是流机制中的第一步,主要描述和捕获进程有关的概念。
捕获进程是Oracle的可选后台进程(CPnn),用来捕获联机重做日志文件中的数据库对象的DML和DDL操作。
逻辑改变记录(Logical Change Record)LCRs:LCR就是通过指定的格式描述数据库对象的改变。捕获进程负责从联机重做日志中捕捉到对象的改变,并将其转化为LCR的格式。捕获进程捕捉两种类型的LCR:row LCRs和DDL LCRs。
Row LCRs:一条Row LCR描述一跳记录的修改或者描述一条记录的一个LOB列。每条Row LCR包含下列信息:源数据库名字、DML语句的类型、表的SCHEMA名字、表名、raw tag、当前事务的标识、SCN、变化记录的OLD VALUE和NEW VALUE。
DDL LCRs:一条DDL LCR描述数据定义语言(DDL)的变化。每条DDL LCR包含下列信息:源数据库名字、DDL语句的类型、DDL目标对象的名字、DDL目标对象的类型、DDL语句的内容、登陆用户名称、执行DDL的SCHEMA名字(如果DDL中没有明确指出SCHEMA名称的话)、基表所属用户名、基本名称、RAW TAG、当前事务的标识和SCN。
捕获规则:捕获进程可以根据用户定义的规则进行捕获。每个规则说明捕获数据库中哪个对象的修改和捕获哪知类型的修改。表级规则在指定表上捕获捕获DML或DDL修改;方案规则在指定方案中捕获DML或DDL修改;全局规则捕获数据库中所有的DML或DDL。注意,捕获进程永远不会捕获SYS和SYSTEM方案中的修改。
捕获支持的数据类型包括:CHAR、VARCHAR2、NCHAR、NVARCHAR2、NUMBER、DATE、CLOB、BLOB、RAW、TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIME STAMP WITH LOCAL TIME ZONE、INTERVAL YEAR TO MONTH、INTERVAL DAY TO SECOND。
不支持的数据类型包括:NCLOB、LONG、LONG RAW、BFILE、ROWID、UROWID,以及用户自定义对象,比如:嵌套表、数组等。
流捕获支持的DML操作有:INSERT、UPDATE、DELETE、MERGE以及LOB的分段更新。不支持的DML包括:CALL、EXPLAIN PLAN、LOCK TABLE。另外,对临时表、索引组织表和对象表的所有DML操作都是无法捕获的。
流捕获不支持的DDL操作包括:ALTER DATABASE、CREATE CONTROLFILE、CREATE DATABASE、CREATE PFILE、CREATE SPFILE。
流捕获机制不支持下列语句:ALTER SYSTEM、ALTER SESSION、SET ROLE以及PL/SQL的调用。另外流机制也不支持使用DBMS_REDEFINITION包进行的在线重定义操作。
如果SQL语句指定了NOLOGGING或UNRECOVERABLE 语句,那么当前SQL语句影响的记录无法被流捕获。可以设置数据库级的FORCE LOGGING,强制所有操作都必须写重做日志,这时候表级和语句级指定的NOLOGGING语句将失效。
如果SQLLOADER程序的控制文件中指定了UNRECOVERABLE语句,则SQLLOADER导出的数据无法被流捕获。解决的方法是在源和目标数据库执行同样的数据装载操作,或者在使用SQLLOADER的时候避免UNRECOVERABLE语句。如果设置了数据库级的FORCE LOGGING参数,则UNRECOVERABLE语句失效。
SUPPLEMENTAL LOGGING:开启了SUPPLEMENTAL LOGGING后,在重做日志中记录UPDATE操作时会记录一些额外的列。SUPPLEMENTAL LOGGING包括数据库级和表级两种类型,而表级SUPPLEMENTAL LOGGING又可以选择UNCONDITIONAL和CONDITIONAL日志组。
UNCONDITIONAL日志组:只有表被更新就会记录指定列的前映像,也称为ALWAYS日志组。CONDITIONAL日志组:只有日志组中的列别更新时,才会记录所有指定列的前映像。
如果需要使用一个或多个应用进程,则必须满足下列条件:
源数据库中所有构成表的主键的列必须是UNCONDITIONAL日志组的成员或者设置DATABASE SUPPLEMENTAL LOGGING OF PRIMARY KEY。
如果应用进程数大于1,则源数据库中所有构成复合唯一约束的列必须是CONDITIONAL日志组成员。
如果应用进程数大于1,则源数据库中所有构成复合外键约束的列必须是CONDITIONAL日志组成员。
源数据库中所有替代键列必须是UNCONDITIONAL日志组成员。
冲突解决方案中涉及的列的个数如果超过一个,则这些列都是必须是CONDITIONAL日志组成员。
被DML句柄或错误句柄指明用于更新或分段更新LOBs的列必须是UNCONDITIONAL日志组成员。
被RULE或基于RULE进行的转换所使用的列必须是UNCONDITIONAL日志组成员。
如果在目标数据库指定了行子集,则在目标数据库表中出现的列以及作为行子集的条件列都必须是UNCONDITIONAL日志组成员。
流的实例化:如果计划使用流的捕获来建立复制机制的话,那么目标数据库必须包含数据库对象的一个拷贝。如果这个拷贝不存在,在把变化数据复制到目标数据库前必须实例化这个对象。实例化的典型方法是利用exp/imp。
在实例化之前需要对表进行准备,使得捕获进程知道从哪个SCN开始捕捉表的修改。通过调用这个准备过程,记录每个对象的最小SCN号,这个最小的SCN号会被用来进行对象的实例化。
当满足下列任意条件时,必须执行准备过程来同步流机制相关的数据字典信息:
捕获进程的规则组中填加一个或多个规则;(通过DBMS_RULE_ADM包填加的规则需要手工进行准备,通过DBMS_STREAMS_ADM包填加的规则会自动进行准备工作)
捕获进程的规则组中修改一个或多个规则;
传播进程的规则组中填加一个或多个规则;
传播进程的规则组中修改一个或多个规则;
流机制建立的数据字典在源数据库和目标数据库是异步的,当执行准备过程时,源数据库会讲流数据字典填加到重做日志中,当日志中的内容传播到目标数据库时,目标数据库会同步流的数据字典信息。
当使用EXP/IMP进行实例化时,表的SUPPLEMENTAL LOG GROUP仍然会保留。但是数据库级的SUPPLEMENTAL LOG则不会保留,即使执行的全库EXP/IMP。
开始SCN、捕捉SCN和应用SCN
开始SCN:捕获进程开始捕捉变化的SCN号。默认情况下开始SCN对应着捕获进程建立的SCN。如果建立捕获进程之后之后没有直接启动而是在两天以后开始启动捕获,那么捕获进程会自动到归档日志中去寻找两天前的日志,找到建立捕获进程的SCN,然后开始捕捉。可以在建立的时候设置捕获进程的开始捕获SCN,也可以改变捕获进程的开始捕获SCN,但是必须保证开始捕获SCN必须大于第一个捕获进程在数据库中的建立SCN。
捕获SCN:指捕获进程所捕获的最近修改的SCN。
应用SCN:捕获进程的应用SCN指相关应用进程最后出队列的事件的SCN。
捕获进程与RESTRICTED SESSION:当数据库使用STARTUP RESTRICT模式启动的时候,捕获进程不会启动,只有数据库关闭正常启动后,捕获进程才会启动。如果使用ALTER SYSTEM ENABLE RESTRICTED SESSION语句,则不会影响当前已经启动的捕获进程。如果停掉捕获进程,则捕获进程只能当DISABLE RESTRICTED SESSION的时候才能重新启动。
捕获进程与RAC环境:如果在RAC环境中配置了一个或多个捕获进程,则必须满足以下条件:
在RAC环境中,捕获进程必须读取所有的实例的修改,因此必须读取归档重做日志。这要求归档重做日志必须对每个实例都是可以访问的;
对DBMS_CAPTURE_ADM.START_CAPTURE过程的调用必须在拥有捕获进程队列的那个实例进行。对其他过程和函数的调用则可以在任意一个实例中进行;
SUPPLEMENTAL LOG的说明必须在每个实例上进行。如果实例关闭都重启,不需要再次说明,也不需要对新增实例进行说明;
初始化参数ARCHIVE_LAG_TARGET必须设置为大于0的值。
如果包含捕获进程队列的实例不可用,则队列的所有权自动转换到RAC的其他实例上。如果这种情况发生,需要连接到拥有队列的实例,执行START_CAPTURE过程来重新启动捕获进程。可以通过DBA_QUEUE_TABLES数据字断表来查询队列表拥有实例。
捕获进程结构:
捕获进程是ORACLE后台进程,进程的名称是cpnn,nn是捕获进程编号,范围是01~99。捕获进程使用LOGMINER机制从在线重做日志中捕获变化,流机制会自动配置LOGMINER。可以创建、修改、启动、停止和删除捕获进程,且可以建立捕获规则来控制捕获哪些改变。
捕获进程的成员:
当捕获进程并行参数设置大于等于3时,则捕获进程包括:
一个reader server:从联机重做日志中读取修改。
一定数量的preparer servers:将reader server发现的修改格式化为LCR。数量等于并行参数设置减2。
一个builder server:将preparer servers创建的LCR按照SCN顺序合并,合并后将LCR加入到于捕获进程关联的序列中。
LOGMINER的设置:
由于捕获进程需要使用LOGMINER,且LOGMINER默认表空间为SYSTEM,应该使用DBMS_LOGMNR_D.SET_TABLESPACE过程为LOGMINER设置单独的表空间。
当一个数据库中运行多个捕获进程的时候,需要将初始化参数LOGMNR_MAX_PERSISTENT_SESSIONS的值大于等于捕获进程数。且需要适当增加SGA的大小。
捕获进程可以通过DBMS_STREAMS_ADM包和DBMS_CAPTURE_ADM建立。由于使用了很多默认设置,利用DBMS_STREAMS_ADM包建立捕获进程相对简单,使用DBMS_CAPTURE_ADM包可以进行更加灵活的设置。
如果使用DBMS_CAPTURE_ADM包的CREATE_CAPTURE过程来创建捕获进程,则需要手工调用准备过程PREPARE_TABLE(SCHEMA/GLOBAL)_INSTANTIATION,为捕获进行准备工作。
以下过程可以创建捕获进程:
DBMS_STREAMS_ADM.ADD_TABLE_RULES、DBMS_STREAMS_ADM.ADD_SCHEMA_RULES、DBMS_STREAM_AMD.ADD_GLOBAL_RULES和DBMS_CAPTURE_ADM.CREATE_CAPTURE。
注意:一旦建立了捕获进程就不要再修改数据库的DBID和DBNAME。
创建数据字典副本:当数据库中第一次创建捕获进程的时候,流会建立数据字典的副本——流数据字典,用来进行捕获和传播。开始时,流数据字典和主数据字典在捕获进程创建时是一致的。
由于捕获进程从重做日志中捕获的动作要比系统中的实时修改要慢,而已,捕获进程可能被停止,因此为捕获进程创建单独的数据字典是必要的。因为捕获进程必须使用当时的数据字典来进行捕获,而这时的主数据字典可能已经发生了变化。
流数据字典在捕获进程捕获到DDL语句时进行更新。流数据字典根据DDL发生的时间进行更新,从而保证了流数据字典总可以正确的对应捕获进程所需的字典信息。
当捕获进程决定是否对表的DDL进行捕获,捕获进程会自动将修改信息添加到流数据字典。Oracle评估捕获规则,只要有一个规则评估为TRUE或MAYBE,则流数据字典的修改被捕获进程捕获。
由于流数据字典的创建是在第一次建立捕获过程的时候,因此第一次创建捕获过程需要较多的时间,具体时间长短取决于数据库中对象的数量。
多个捕获进程使用同一个流数据字典。由于流数据字典是多版本的,每个捕获进程都和流数据字典是同步的。
归档模式和捕获进程:如果可能捕获进程就会读取联机重做日志,否则就读取归档重做日志。因此,数据库必须配置为归档模式。查询视图DBA_CAPTURE的APPLY_SCN列可以确定应用进程出队列的最近的SCN。当捕获进程落后了,捕获进程会进行从读联机重做日志到读归档重做日志的无缝转换,当捕获进程赶上以后,也会进行从读归档重做日志到读联机重做日志的无缝转换。
捕获进程参数:
常用的捕获进程参数包括:并行度parallelism和捕获进程启动停止的限制disable_on_limit、time_limit和message_limit。
捕获进程规则的评估:
1、在重做日志中发现修改
2、重做日志中修改的预过滤。如果日志中的修改在转化为LCR后,会使得一个以上的规则评估为TRUE,则修改记录被保留,否则,修改记录被过滤。
3、将预过滤的修改转化为LCR。
4、执行LCR过滤。这一步,LCR被分为两部分,一部分将被加入到队列中,另一部分将被丢弃。
5、丢弃那些不加入到队列的LCR。
6、将剩余LCR添加到队列中。
捕获进程状态维持:
捕获进程在数据库关闭并重启后会维持关闭前的状态。