前一章我们实践了一把streams同步单表的过程,看起来很简单是不是(如果你觉着复杂,那不是因为streams本身操作复杂,而是为了配置好streams前期的准备工作较复杂),事实上也确实很简单,由小能见大,我们从上述示例中应该也能看出streams的操作方式就是捕获(capture)->传播(propagation)->应用(apply),不管是表也好,schema也好,database也好,都是遵循这个操作过程,下面逐一介绍捕获传播和应用进程,俺尽可能做到清晰简单直白,但限于个人理解和自身水平,如描述有误请自行鉴别:))。另,本章文字描述较多,内容相对枯燥,阅读前要做好准备,如有心直接上手更高级的实践配置,可跳过本节,浏览第二部分。

捕获(Capture)

  众所周知,数据库的修改操作均会被记入redolog(表钻牛角尖,俺指通常情况下),以便在发生错误时,能有途径修正。而Capture进程做为oracle的一个后台进程天生就拥有读取redolog的本领,因此它也就具有了捕获dml,dll修改操作的能力。

  Capture 进程将修改格式化为指定的格式存入message定义为 LCRs 并将其置入队列(queue)。由于运行中的capture进程自动基于其自己的规则捕获修改,因此又被称为:隐式捕获(implicit capture)。

    提示:什么是LCR

      capture 进程捕获数据库的操作,例如表/schema甚至整个数据库的修改等。这些修改都会记入redo,而capture进程就是根据redolog分析数据库中的修改并格式化保存为message,这些message即被称为:logical change record (LCR)。捕获进程通过定义的rule来确定哪些修改会被捕获,这些被捕获的修改称为captured messages。

  因此:Messages->LCRs->Captured message

  LCRs 也分两种:

  A>.row LCR :包括DML操作产生的修改信息,注意由于单条dml sql语句也有可能触发多条记录的修改,因此一条dml修改操作也可能产生多条row LCR,另外对于单行中大字段类型的修改比如long,lob也可能产生多条row LCR;

  每条rowLCR被封装成LCR$_ROW_RECORD的对象类型,包含下列属性:

  • source_database_name :触发修改操作的数据库
  • command_type :触发修改操作的命令类型,比如: INSERT, UPDATE, DELETE, LOB ERASE, LOB WRITE, or LOB TRIM 。
  • object_owner :对象属主
  • object_name :对象名称
  • Tag :标签,可用于追踪LCR
  • transaction_id :触发修改的DML语句所属事务ID
  • Scn :发生修改时的SCN( system change number )
  • old_values :DML修改前的值,不过注意不同的dml操作产生值也不同,比如 UPDATE or DELETE 的旧值就是修改前的值,而对于INSERT则该列为空
  • new_values :DML修改后的值,基于相同的原因,不同的dml操作也会产生不同的值,比如 UPDATE or INSERT 的值即修改后的值,而DELETE操作则该列为空

  B>.DDL LCR :包括ddl操作产生的对象修改信息,DDL LCR包括下列的信息:

  • source_database_name :同rowLCR
  • command_type :同rowLCR
  • object_owner :同rowLCR
  • object_name :同rowLCR
  • object_type :对象类型,比如TABLE/VIEW/PACKAGE
  • ddl_text :执行的DDL语句
  • logon_user :执行DDL语句的用户
  • current_schema :执行DDL语句的schema
  • base_table_owner :基表属主(如果有的话,当然通常没有,但是对于某些操作比如触发器触发的的修改,则基表即是触发表)
  • base_table_name :基表名称,其它同上。
  • tag :同rowLCR
  • transaction_id :同rowLCR
  • scn :同rowLCR

提示:

    不管是rowLCRs或DDL LCRs都包括源数据库名称,为避免在propagation或apply时出现问题,ORACLE建议不要随便修改源数据库名称。

1、捕获方式

  Capture 进程即可以在本地捕获 ,即本地捕获进程(local capture process),也可以在远程其它数据库执行捕获,即下游捕获进程(downstream capture process),执行下载捕获的数据库也被称为downstream数据库,甚至还可以同时配置本地捕获和下游捕获 。

  本地捕获比较简单,是指capture进程运行于本地,如图所示:

  

  下游捕获就要复杂一点点,因为它要涉及到将本地产生的redologs发送至远端执行捕获的数据库,说到发送redologs让回忆起了standby是吧,对,此处确实与standby有所关联,发送redologs应用的技术是一样的(正好趁此机会再复习一下),因此下游捕获也不得不被分成两类:

  A. 实时下游捕获 (real-time downstream capture)

  Redo 传输服务通过LGWR发送redo数据到downstream数据库,downstream数据库端通过RFS(remote file server)进程接收并保存到本地的standby redolog文件中,归档进程读取standby redo并写入归档文件,downstream端capture进程即可从standby redo中捕获修改,也可以从archive redo中捕获修改,当然,优先从standby redo中获取。

  如图:

  

  B. 归档下游捕获 (archived-log downstream capture)

  这种方式也很有意思,你可以通过各种方式(redo传输服务,ftp,dbms_file_transfer包等等)复制源数据端生成的归档文件到downstream数据库。然后再由目标数据库的capture进程进行捕获生成LCRs保存入queue。

  如图:

  

  Downstream 捕获看起来步骤更多,逻辑相对较复杂,但其存在并非毫无意义,实际上downstream是oracle自10g版本(实时捕获最低需要10gr2)才开始提供的特性,目的就是为了节省了源库的宝贵资源,这样就可以将捕获工作转移到downstream端做。

2、支持的数据类型

  对于dml操作,capture进程支持捕获下列数据类型发生的修改:

  • VARCHAR2
  • NVARCHAR2
  • NUMBER
  • LONG
  • DATE
  • BINARY_FLOAT
  • BINARY_DOUBLE
  • TIMESTAMP
  • TIMESTAMP WITH TIME ZONE
  • TIMESTAMP WITH LOCAL TIME ZONE
  • INTERVAL YEAR TO MONTH
  • INTERVAL DAY TO SECOND
  • RAW
  • LONG RAW
  • CHAR
  • NCHAR
  • CLOB
  • NCLOB
  • BLOB
  • UROWID

  与逻辑standby类型,capture对于下列的类型同样不支持:BFILE, ROWID, and user-defined types (including object types, REFs, varrays, nested tables, and Oracle-supplied types)。应用transparent data encryption的列也不被支持,capture进程捕获上述不支持类型时会触发一条错误信息并写入trade文件。默认rule下,捕获进程会自动disable。

  提示:关于rule的信息也非常多,并且streams提供了positive rule set 和negative rule set以实现更灵活的捕获规则,本文不准备逐一介绍,除后期实践部分用到时针对具体设置进程说明外,更全面的关于rule的设置,也许某天会以专门附章形式提示,有耐心的朋友不妨持续等待,没耐心的话,黑黑,也得等。

3、支持的操作

  A.DML 捕获

  STREAMS 支持:INSERT,UPDATE,DELETE,MERGE/LOBs UPDATE触发的修改。

  注意:

  1. Capture 进程会将merge产生的修改转换成insert或update,因为对于rowLCR来说,MERGE并不是一个有效的命令类型。

  2. 对于索引表不能包含ROWID/UROWID/User-defined types (including object types, REFs, varrays, and nested tables),不然Capture进程会报错。

  3. Capture 进程忽略如CALL,EXPLAIN PLAN或LOCK TABLE命令。

  4. Capture 进程不会捕获临时表或对象表中的修改。

  5. Capture 进程不会捕获类似sequence.nextval之类的操作,因此对于双向复制的streams环境中sequence的赋值需要注意。

  B.DDL 捕获

  通常情况下capture进程根据定义的rule sets执行ddl捕获,不过无论如何下列的几种ddl操作都不会被捕获:

  ALTER DATABASE

  CREATE CONTROLFILE

  CREATE DATABASE

  CREATE PFILE

  CREATE SPFILE

  FLASHBACK DATABASE

  Capture 进程捕获的是ddl语句而并非ddl语句执行产生的结果(注意这点)。举个例子,你在源端执行analyze语句,capture并不会捕获analyze生成的那些统计信息,而只是analyze这条语句。只有一种例外即create table as select这类语句,对于这种语句它除了捕获语句本身外,还需要捕获select的列(做为insert rowLCR)。

    注意:并非ddl被捕获就肯定会被应用,后面我们实践的时候会有相关的示例演示为啥捕获没问题,但却无法应用。