1 引言
Oracle Stream功能是为提高数据库的高可用性而设计的,在Oracle 9i及之前的版本这个功能被称为Advance Replication.....闲话太多,直入主题:
2 概述
目前的生产库架构为:在线主库是oracle10g的rac,数据库版本:10.2.0.5.0,有一个物理data guard,数据库版本:10.2.0.5.0,现在由于业务需求,需单独的
建立一个stream数据库,用来作为酒窖独立数据库,目的实时同步在线数据库的某些表,最终的解决方案:
downstream real-time
单向异地实时捕获的stream
主数据库(RAC):
操作系统:linux 2.6.18-194.el5
IP地址:10.1.x.x,10.1.x.x,10.1.x.x
数据库:Oracle 10.2.0.5.0
ORACLE_SID:axx
Global_name:axx
从数据库:
操作系统:linux 2.6.18-194.el5
IP地址:10.1.x.x
数据库:Oracle 10.2.0.5.0
ORACLE_SID:cxx
Global_name:cxx
3 环境准备
3.1 设定初始化参数
使用pfile的修改init.ora文件,使用spfile的通过alter system命令修改spile文件。主、从数据库分别执行如下的语句:
Sqlplus '/ as sysdba'
alter system set aq_tm_processes=2 scope=both sid='*';
alter system set global_names=true scope=both sid='*';
alter system set job_queue_processes=10 scope=both sid='*';
alter system set parallel_max_servers=20 scope=both sid='*';
alter system set undo_retention=3600 scope=both sid='*';
alter system set nls_date_format='YYYY-MM-DD HH24:MI:SS' scope=spfile sid='*';
alter system set streams_pool_size=200M scope=spfile sid='*';
alter system set utl_file_dir='*' scope=spfile sid='*';
alter system set open_links=4 scope=spfile sid='*';
执行完毕后重启数据库。
3.2 将数据库置为归档模式
设置log_archive_dest_1到相应的位置;(设定log_archive_start为TRUE,即启用自动归档功能--oracle10g来说,该参数是一个过期参数,可以忽略);
设定log_archive_format指定归档日志的命令格式。
-- alter system reset log_archive_start scope=spfile sid='*'; 过期参数
sqlplus '/ as sysdba'
alter system set LOG_ARCHIVE_CONFIG ='dg_config=(axx,bxx,cxx)'; ---主从+data guard
LOG_ARCHIVE_DEST_2参数对应原来的data guard,不需要修改!
alter system set LOG_ARCHIVE_DEST_3 = 'service=cxx lgwr sync noregister VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) db_unique_name=cxx'; --主
alter system set log_archive_dest_1='location=/../..' scope=spfile; ---主从(本地归档日志存放位置)
alter system set log_archive_format=' arch%t_%s_%r.arc' scope=spfile; ---主从
alter system set standby_archive_dest='/../..' scope=spfile; ---从(rac数据库的归档日志存放位置)
---以下步骤可以省略,如果已经是归档模式了(在线生产库应该很少有不是归档模式的吧)
shutdown immediate;
startup mount;
alter database archivelog;
alter database open;
3.3 创建stream 管理用户
3.3.1 创建主环境stream管理用户
#以sysdba身份登录
connect / as sysdba
#创建主环境的Stream专用表空间
create tablespace tbs_stream datafile '/oracle/oradata/UAT/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 strmadminpassword 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专用表空间,我的从库用了ASM,这一步也可以参见3.3.1
create tablespace tbs_stream datafile '/oracle/oradata/UAT/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 strmadminpassword
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)中添加从数据库的配置(3个节点都加上)。
cxx =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.1.x.x)(PORT = 1515))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = cxx)
)
)
3.4.2配置从环境tnsnames.ora
从数据库(tnsnames.ora)中添加主数据库的配置。
#如下配置的前提是host文件已经添加过域名解析
axx =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = axx1-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = axx2-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = axx3-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = axx)
)
)
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,执行“alter database rename global_name to xxx”。
select * from global_name;
3.6.1创建主数据库数据库链
#以strmadmin身份,登录主数据库。
connect strmadmin/strmadminpassword
#建立数据库链
create database link cxx connect to strmadmin identified by strmadminpassword using 'cxx';
--测试
select * from dual@cxx;
3.6.2创建从数据库数据库链
#以strmadmin身份,登录从数据库。
connect strmadmin/strmadminpassword
#建立数据库链
create database link axx connect to strmadmin identified by strmadminpassword using 'axx';
--测试
select * from dual@axx;
3.7 由于是下游实时捕获,需要在从库创建standby redo logfile,对应主库-rac的每一个实例都要创建相应的standby redo log日志组,
且要比主库的日志组多一组
alter database add standby logfile thread1 group 14 ('/../../../stdbyredo141.log','/../../../stdbyredo142.log') size xxm;
alter database add standby logfile thread1 group 15 ('/../../../stdbyredo151.log','/../../../stdbyredo152.log') size xxm;
.....
alter database add standby logfile thread3 group 49 ('/../../../stdbyredo491.log','/../../../stdbyredo492.log') size xxm;
----------到此为止,所有的准备工作基本做完了,然后rac和从库都重新启动一下吧
重启之后,从库可能会报错:
ORA-16009: remote archive log destination must be a STANDBY database
直接在rac库执行:
alter system set LOG_ARCHIVE_DEST_STATE_3 = 'ENABLE' scope=both sid='*';
这个位置激活后,主库切下日志试试,我的做法一般都是主从都开着窗口实时动态查看告警日志,然后分别执行相关操作!
3.9 在从库执行maintain_tables包(strmadmin用户)
DECLARE
tbls DBMS_UTILITY.UNCL_ARRAY;
BEGIN
tbls(1) :='need_stream_user.table1';
tbls(2) :='need_stream_user.table2';
...
tbls(n) :='need_stream_user.tablen';
DBMS_STREAMS_ADM.MAINTAIN_TABLES(
table_names => tbls,
source_directory_object => 'source_directory',
destination_directory_object => 'destination_directory',
source_database => 'axx',
destination_database => 'cxx',
perform_actions => true, --实际执行带有network的导入操作
dump_file_name => 'export_tables_kasaur.dmp',
log_file => 'export_tables_expdp_kasaur.log',
script_name => 'configure_rep_kasaur.sql',
script_directory_object => 'destination_directory',
bi_directional => false,
include_ddl => true, --包含源库的ddl操作
instantiation => DBMS_STREAMS_ADM.INSTANTIATION_TABLE_NETWORK);
END;
/
---由于执行这个包的时候,会同时把相关表的数据同时导入到从库,应该会需要一定时间,
待执行完之后,从库会产生propagation、capture和apply三个进程,正常情况下,这三个进程状态应该都是enable的,可用如下命令查看:
select propagation_name as name,status,ERROR_MESSAGE from dba_propagation
union all
select CAPTURE_NAME,status,ERROR_MESSAGE from dba_capture
union all
SELECT apply_name,status,error_message from dba_apply;
---------------------------------------------------------------
PROPAGATION$_461 ENABLED
axx$CAP ENABLED
APPLY$_axx_576 ENABLED
之后在从库修改capture进程属性,启用实时捕获
BEGIN
DBMS_CAPTURE_ADM.SET_PARAMETER(
capture_name => 'axx$CAP',
parameter => 'downstream_real_time_mine',
value => 'y');
END;
/
---如果执行上述操作报错,可先停止capture进程,同时停止实时捕获(虽然没有启动起来,但是做下停止操作,再进行后续操作会很好):
--停捕获进程
begin
dbms_capture_adm.stop_capture(
capture_name => 'axx$CAP');
end;
/
--停实时捕获
BEGIN
DBMS_CAPTURE_ADM.SET_PARAMETER(
capture_name => 'axx$CAP',
parameter => 'downstream_real_time_mine',
value => 'n');
END;
/
----之后再开启应该就没什么问题了
begin
dbms_capture_adm.start_capture(
capture_name => 'axx$CAP');
end;
/
BEGIN
DBMS_CAPTURE_ADM.SET_PARAMETER(
capture_name => 'axx$CAP',
parameter => 'downstream_real_time_mine',
value => 'y');
END;
/
------------
我这里实际情况是只实时同步了几十张表,当数据同步完了之后,主站数据变更导致从库的apply进程abort掉了,查询错误信息,发现是从库的某个
trigger导致的,之后把trigger删了,重新启动apply进程就ok了。
由于是表级别的单项复制,不可避免的会产生update冲突,正式上线之前最好先解决掉,具体操作脚步如下:
select 'DECLARE
cols DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := ''' || column_name || ''';
DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(object_name => ''need_stream_user.' ||
table_name ||
''', method_name => ''OVERWRITE'',resolution_column => ''' ||
column_name || ''',column_list => cols);
END;
/'
from all_tab_columns
where table_name in ('table1_name','table2_name'..'tablen_name') and wner='need_stream_user';
--该操作是产生需要解决冲突的相关表的执行脚本的语句,生成之后,在从库执行脚本就ok了!
4.0 在源库归档当前日志,使得capture进程切换到standby redo logfile中捕获数据
alter system archive log current;
此后在目标库的alert中可以发现如下记录,表明已经开始实时捕获了:
LOGMINER: Begin mining logfile for session 41 thread 3 sequence 5847, /../../../stdredo331.log
4.1 相关检查处理
select propagation_name,destination_dblink,status,ERROR_MESSAGE from dba_propagation;
select error_message from dba_recoverable_script_errors;
select queue,msg_id,MSG_STATE from capture_queue_table;
select OBJECT_OWNER,OBJECT_NAME,METHOD_NAME,RESOLUTION_COLUMN,COLUMN_NAME from dba_apply_conflict_columns;
select * from v$streams_capture;
select schema,qname,destination,schedule_disabled,failures,last_error_msg
from dba_queue_schedules;
SELECT
queue_schema, queue_name, unbrowsed_msgs, overspilled_msgs,
memory_usage, publisher_state
FROM V$BUFFERED_PUBLISHERS;
exec DBMS_CAPTURE_ADM.ABORT_TABLE_INSTANTIATION(table_name => 'need_stream_user.table_name'); --删掉不需要同步的表
...
...多的是,网上找吧
4.2 清除stream配置
在从库执行(只是我的操作):
begin
dbms_propagation_adm.stop_propagation(
propagation_name => 'PROPAGATION$_461');
end;
/
begin
dbms_capture_adm.stop_capture(
capture_name => 'axx$CAP');
end;
/
begin
dbms_apply_adm.stop_apply(
apply_name => 'APPLY$_axx_576');
end;
/
exec DBMS_STREAMS_ADM.remove_streams_configuration();
---------------------------
后记:线上库stream运行到现在有2天了,今天早上过来发现capture进程莫名abort掉了,查询日志,报错信息如下:
ORA-01341: LogMiner out-of-memory
ORA-01280: Fatal LogMiner Error.
内存不够,直接增加内存:
exec dbms_capture_adm.set_parameter('axx$CAP','_SGA_SIZE','100');
然后重新起起来,运行没5分钟,propagation进程抛出警告:
ORA-25307: Enqueue rate too high, flow control enabled
但是状态依然是enable的,大概意思是入队速度太快了,导致应用跟不上,不过一段时间后又会自动应用起来,之后就没过多的过问,不知道
是不是oracle的bug,有待查证!
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25618347/viewspace-711122/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/25618347/viewspace-711122/