4.  应用DDL修改

4.1.  APPLY 进程忽略的DDL语句

  APPLY 应用不支持下列类型的DDL语句:

  • ALTER MATERIALIZED VIEW
  • ALTER MATERIALIZED VIEW LOG
  • CREATE DATABASE LINK
  • CREATE SCHEMA AUTHORIZATION
  • CREATE MATERIALIZED VIEW
  • CREATE MATERIALIZED VIEW LOG
  • DROP DATABASE LINK
  • DROP MATERIALIZED VIEW
  • DROP MATERIALIZED VIEW LOG
  • RENAME

  如果apply进程在应用DDL LCR时发现不支持的操作,会自动忽略该LCR并记录一条信息到apply进程的trace文件。

    注意:

    Alter objectType objectName rename 语句是能够被apply应用支持的,比如alter table rename之类的。Snapshot是materialized view的同义词,因此snapshot相关的语句也不会被apply应用支持。

4.2.  Streams 复制环境中的数据结构

  数据结构不仅包含数据文件、表空间、回滚段之类物理结构,还有比如表结构等等逻辑结构。捕获的DDL要在目标端完全应用,要么确保源和目标端的结构一致,要么在源端执行sql语句时不要包含目标端没有的对象。

  比如说,一项对表做修改的DDL要想在目标端成功应用,需要考虑下列诸项因素:

  • Create table 的存储参数相同
  • 如果指定了回滚段,表空间等项,则该表空间/回滚段必须确实存在于目标端。
  • 如果指定了分区信息,则分区在目标端也必须有效。

  注意DDL应用时,执行ddl的shcema必须已经存在于目标端数据库。

4.3.  系统产生的对象名称

  应尽可能避免系统产生的对象名称。因为源端捕获的实际还是ddl语句,这样在目标端应用后,如果是由系统自动生成名称,则源端和目标端名称有可能会不一致,这就有可能导致后续应用的一些问题。

  比如说源端执行这样的语句:

  CREATE TABLE  tbl  (n1 NUMBER  NOT NULL); 

  则系统会自动创建一个not null的约束,假设源端名称为定义为sys_000115,目标端应用create table语句时,可能为该约束创建一个非sys_000115的名字(毕竟源端与目标端并非一模一样),当你再执行删除该约束时:

  Alter table tbl drop constraint sys_000115;

  源端可以正确执行,但目标端在应用该语句时就有可能报找不到sys_000115对象的错误,正确的方式,应该是在创建时指定名称,比如:

  Create table tbl (n1 number constraint ck_tbl_nlnull not null);

4.4.  CREATE TABLE AS SELECT 语句的执行

  应用create table as select语句时,apply进程执行如下两个步骤:

  • 目标端执行CREATE TABLE AS SELECT语句,不过只创建表并不生成数据。如果失败则apply进程返回错误信息,否则继续执行下一步。
  • 插入数据。注意这一步实际插入的记录可能会受到capture/propagation/apply进程的自定义规则影响,实际插入记录有可能与源端不同。

5.  触发器属性

  你可以通过DBMS_DDL.SET_TRIGGER_FIRING_PROPERTY过程控制DML/DDL触发器的触发,该过程控制触发器是否只触发一次。

  如果该过程的fire once参数设置为true(默认情况下该参数即是true,你可以通过DBMS_DLL.IS_TRIGGER_FIRE_ONCE函数检查触发器的触发属性设置),下列情况不会触发触发器。

  • 相关更新由apply进程产生。
  • 执行DBMS_APPLY_ADM.EXECUTE_ERROR/EXECUTE_ALL_ERRORS过程产生的修改。

  举个例子,Schema:hr中创建触发器update_job_history,当employees表中job_id或department_id被更新时自动插入记录到job_history表,当前streams复制环境如下:

  • dbs1.net 源端capture进程同时捕获两张表的修改
  • Propagation 传播修改到目标端dbs2.net
  • Apply 进程在目标端应用修改
  • Update_job_history 触发器存在于源端和目标端。

  如果目标端dbs2.net中update_job_history触发属性不是fire once的话,实际操作如下:

  • 源端dbs1.net中employees.job_id被修改
  • Update_job_history 被触发,新记录插入到job_history表
  • 源端的capture进程同时捕获到employees和job_history的修改
  • 修改被传播到目标端dbs2.net
  • 目标端应用这两表的修改
  • 目标端应用employees表修改时update_job_history触发器再次被触发,又有记录被插入job_history表

  由上可知,job_history中实际是产生了重复记录了的,多数情况下我们可能是不希望产生这种状况,如果我们设置update_job_history的触发属性为fire once(或者在创建触发器时指定on schema子句),则dbs2.net端就不会再被触发了。

6.  APPLY 进程支持的数据类型

  下列数据类型可被apply进程支持:

  • 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

  不支持的类型有:BFILE, ROWID, and user-defined type (including object types, REFs, varrays, nested tables, and Oracle-supplied types)等。另外,apply进程不支持transparent data加密过的数据,不管加密数据是什么类型。

7.  APPLY 进程与受限连接

  如果以startup restrict模式启动数据库的话,apply进程就不会被启动。如果是以alter system enable restricted session语句将数据库置为restrict模式的话,对于当前正在运行的apply进程不会有影响,但不会再有新的apply进程启动,直到disable restricte。

8.  APPLY 进程与RAC

  RAC 环境下apply进程是与实例绑定的,即各实例管理各自的apply进程,如果某个apply进程因某种原因不可用的话,队列ownership自动转换至集群中其它实例。同时apply进程也会随着队列转移至相应实例。另外,激活状态的apply进程所在实例不可用的话,apply进程会自动在新实例上启动,而未激活状态的apply进程所在实例不可用的话,apply进程在新实例中仍然保持未激活状态。

  数据字典DBA_QUEUE_TABLES中记录了队列对应的实例信息,另外在RAC环境中,apply coordinator进程,以及其对应的apply reader server和apply servers运行在相同实例上。

    提示:

    什么是  Reader Server :并行执行服务,capture进程的一部分,用来读取redolog并定位其范围。

    什么是 Apply Servers :apply进程的一部分,包含一个或多个并行执行服务,用于应用LCRs或发送其至适当的apply handlers。

    什么是 Apply Coordinator Process :做为apply进程的一部分同属oracle后台进程,用于从Reader Server中获取事务并发送给Apply Servers。