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。
|