一般oracle dml触发器的fire_once_only属性为true,这样普通用户进程执行dml操作时,rdbms去激活它们,但在logical standby的sql apply进程中是自动禁用,
这样保证了logical standby和主库数据的一致性.当然也可以把触发器的fire_once_only属性改为false,这样sql apply进程也会激活它们.
之前客户的一个报表系统,通过logicalstandby实现,降低了主库的查询压力.但客户希望能将一些不需要的表屏蔽掉,将某些的字段脱敏.屏蔽表可以通过dbms_logstdby.skip
实现.将某些字段进行脱敏,就需要用到触发器这个fire_once_only属性了.
以下演示:
db version:11.2.0.4
--1.在主库建立测试表
create table SCOTT.DEPT
(
deptno NUMBER(2) not null,
dname VARCHAR2(21),
loc VARCHAR2(20)
);
alter table SCOTT.DEPT
add constraint PK_DEPT primary key (DEPTNO) using index ;
--2.在主库SCOTT.DEPT表上建立用于脱敏的触发器
--用sys用户给scott赋予dbms_logstdby包的权限.
grant execute on dbms_logstdby to scott;
--通过dbms_logstdby.is_apply_server()来避免在主库上执行
create or replace trigger scott.trg_dept
before insert or update on scott.dept
for each row
begin
if dbms_logstdby.is_apply_server() then
:new.dname := 'abc';
end if;
end;
--3.在主库上将触发器的fire_once_only属性设置为false
begin
dbms_ddl.set_trigger_firing_property('scott','trg_dept',false);
end;
--4.验证
--在主库中插入数据
insert into scott.dept
select 1,'dev','bj' from dual;
commit;
--在备库中查看数据
select * from SCOTT.DEPT t;
/*
DEPTNO DNAME LOC
1 abc bj
*/
备注:
1.测试中发现dbms_ddl.set_trigger_firing_property('scott','trg_dept',false);要在建完触发器之后就要执行.如果触发器建完,已经有一些对该表的dml操作,再执行
dbms_ddl.set_trigger_firing_property不生效.这时可以disable备库上这个触发器,再enable备库上这个触发器,就可以生效.
2.通过触发器实现这个功能要注意考虑因为主备表中某些字段不致导致备库上sql apply进程终止.