Stream 是Oracle 的消息队列(也叫OracleAdvanced Queue)技术的一种扩展应用。 Oracle 的消息队列是通过发布/订阅的方式来解决事件管理。流复制(Stream replication)只是基于它的一个数据共享技术,也可以被用作一个可灵活定制的高可用性方案。它可以实现两个数据库之间数据库级,schema级,Table级的数据同步,并且这种同步可以是双向的。 Oracle Stream也是通过数据冗余来提高可用性,这一点和Data Guard 类型。
Oracle 高级复制(Oracle advancedReplication) 和流复制(Stream Replication) 是从名称和功能上都相似的两种技术。但前者是基于触发器的,后者是基于日志挖掘(Logminer)技术。
一. Stream 的工作原理
Stream 是Oracle AdvancedQueue技术的一种扩展应用,这种技术最基本的原理就是收集事件,把时间保存在队列中,然后把这些事件发布给不同的订阅者。从DBA的角度来说,就是把捕获Oracle数据库产生的Redo日志,然后把这些日志通过网络传播到多个数据库,其他数据库通过应用这些日志,达到复制变化的作用。
在Stream 环境下,复制的起点数据库叫作Source Database,复制的终点数据库叫作Target Database。在这两个数据库上都要创建一个队列,其中的Source Database上的是发送队列,而Target Database上的是接收队列。
数据库的所有操作都会被记录在日志中。配好Stream环境后,在Source Database上会有一个捕获进程(Capture Process), 该进程利用Logminer技术从日志中提取DDL,DML语句,这些语句用一种特殊的格式表达,叫作逻辑变更记录(Logical Change Record, LCR). 一个LCR对应一个原子的行变更,因此源数据库上的一个DML语句,可能对应若干个LCR记录。这些LCR会保存到Sourece Database的本地发送队列中。然后传播进程(Propagation Process)把这些记录通过网络发送到Target Database的接收队列。在Target Database上会有一个应用进程(Apply Process),这个进程从本地的接收队列中取出LCR记录,然后在本地应用,实现数据同步
二. Data Guard 和Stream 区别
Date Guard有两种类型:physicalstandby 和 logical standby。这两中standby 都有3个功能模块:日志传送;日志接收,日志恢复。两种standby在前两个模块中是一样的,都是通过LGWR或者ARCn进程发送日志,通过RFS进程接受日志。区别在第三个模块:
Physical Standby 使用的是MediaRecovery技术直接在数据块级别进行恢复,因此Physical Standby 能够做到两个数据库的完全同步,没有数据类型限制。
Logical Standby实际是通过Logminer技术,把日志中的记录还原成SQL语句,然后通过ApplyEngine 执行这些语句实现数据同步,因此Logical Standby不能保证数据的完全一致。比如Logical Standby 不支持某些数据类型,这一点在选择Logical Standby时必须要考虑. Logical Standby 不支持的数据类型可以从DBA_LOGSTDBY_UNSUPPORTED是不里查看.
SQL>SELECT * FROM DBA_LOGSTDBY_UNSUPPORTED;
Stream 使用的是LogicalStandby 第三个模块,也就是在Source Database一端,Capture 进程利用Logminer 技术把日志内容还原成LCR,然后发送到Target Database,而在Target database 一端,也是通过Apply Engine 执行这些LCR。因此Stream在使用上也有些限制条件。这些可以从视图ALL/DBA_STREAMS_NEWLY_SUPPORTED, ALL/DBA_STREAMS_UNSUPPORTED 查看stream复制不支持的数据类型。
SQL>SELECT table_name, reason FROMALL_STREAMS_NEWLY_SUPPORTED;
SQL>SELECT table_name, reason FROMDBA_STREAMS_NEWLY_SUPPORTED;
SQL>SELECT table_name, reason FROMDBA_STREAMS_UNSUPPORTED;
SQL>SELECT table_name, reason FROMALL_STREAMS_UNSUPPORTED;
下面以图表的形式列举他们的区别:
Streams
Data Guard
主要目的是数据共享
主要目的是灾难恢复和高可用性
可以多方向同步
只能是单向,从Primary--> Standby
数据粒度可以是数据库,Schema,Table三个级别
只有数据库级别
支持异种平台的同步(Heterogeneous Platforms)
必须同种平台 (Homogeneous Platforms)
参与复制的每个数据库可以读写
只有Primary可以读写,Standby 只读
支持Oracle 和非Oracle 数据库间的同步
只能是Oracle数据库间
三. 前期规划的几点:
1). 确定复制集:如是数据库级还是表级
2). 决定复制站点
3). 决定LCR是本地捕获还是下游捕获
本地捕获:在源数据库进行,从联机日志和归档日志获得LCR
下游捕获:在目标数据库进行,从归档日志获得LCR.
本地捕获可以保护更多的数据,但是会占用源数据库的资源。
4). 决定复制拓扑结构:这时要决定复制数据库的用途,是只用于预防灾难,还是平时保持空闲,或允许用户使用。
四、简单搭建过程
Orcl是原库,vion是目标数据库
1、 初始化设置(主从库执行),执行完重启数据库
alter system setaq_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=250M scope=spfile;
alter system set utl_file_dir='*' scope=spfile;
alter system setopen_links=4 scope=spfile;
alter system set"_job_queue_interval"=1 scope=spfile;
alter system set logmnr_max_persistent_sessions=1 scope=spfile#10g 默认为1,持久的日志挖掘会话数。
注意streams_pool_size一定要够大,因为如果启用了SGA_TARGET,ORACLE可能分配很少内存给stream导致大量信息被spill到磁盘导致查询DBA_APPLY,DBA_CAPTURE,DBA_PROPGATION全部状态ENABLED但就是没有数据被同步。
同时设置_job_queue_interval也是为了提高队列检查时间,防止apply出问题。
2、 确定数据库在归档模式下,否则修改为归档模式
Startup mount
alter database archivelog;
alter database open
archive log list---查看
3、 创建帐户,主从一样
#创建表空间
createtablespace tbs_stream datafile '/home/oracle/data/tbs_stream01.dbf' size 100mautoextend on maxsize unlimited segment space management auto;
#将logminer的数据字典从system表空间转移到新建的表空间,防止撑满system表空间
executedbms_logmnr_d.set_tablespace('tbs_stream');
#用户
createuser strmadmin identified by strmadmin
defaulttablespace tbs_stream temporary tablespace temp;
#授权
grantconnect,resource,dba,aq_administrator_role to strmadmin;
begin
dbms_streams_auth.grant_admin_privilege(
grantee=>'strmadmin',
grant_privileges=>TRUE);
end;
/
4、 配置网络
配置网络服务名
VION =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.9.134)(PORT= 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = vion)
)
)
另一个
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST =192.168.9.132)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)