Este artigo reproduz uma implementação muito simples, que é dada de exemplo na documentação da Oracle, para os casos onde temos tabelas não suportadas nativamente pelo SQL Apply, e que precisam de uma intervenção manual para que seus dados sejam replicados. Essa operação consiste basicamente na criação de uma tabela paralela, e as triggers que farão o trabalho de replicação em cada evento de DML na tabela de origem. O exemplo foi extraído DESTE material oficial.
Criando um objeto do tipo TYPE no primary e uma tabela que o utiliza em uma de suas colunas:
[oracle@fornix1 ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Sun Apr 4 04:09:42 2021
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
SQL> create or replace type SOE.PERSON as object
(
FIRSTNAME varchar2(50), LASTNAME varchar2(50), BIRTHDATE Date );
/ 2 3 4
Type created.
SQL> create table SOE.PERSONS
(
IDNUMBER varchar2(10) , DEPARTMENT varchar2(50), INFO SOE.PERSON ); 2 3
Table created.
Criando a “shadow table” no primary que será populada via trigger:
SQL> create table SOE.PERSONS_LOG
(
T_IDNUMBER varchar2(10),
T_DEPARTMENT varchar2(50),
T_FIRSTNAME varchar2(50),
T_LASTNAME varchar2(50),
T_BIRTHDATE Date
); 2 3 4 5 6 7 8
Table created.
Criando a trigger no primary que populará a shadow table:
SQL> CONN SOE
Enter password:
Connected.
SQL> SHOW USER;
USER is "SOE"
SQL> create or replace trigger flatten_persons
after insert on persons for each row
declare
begin
insert into persons_log
(t_IdNumber, t_Department, t_FirstName, t_LastName, t_BirthDate)
values
(:new.IdNumber, :new.Department,
:new.Info.FirstName,:new.Info.LastName, :new.Info.BirthDate);
end;
/ 2 3 4 5 6 7 8 9 10 11
Trigger created.
Criando a trigger no primary que populará a tabela no ambiente standby de destino:
SQL> create or replace trigger reconstruct_persons
after insert on persons_log for each row
begin
insert into Persons (IdNumber, Department, Info)
values (:new.t_IdNumber, :new.t_Department,
Person(:new.t_FirstName, :new.t_LastName, :new.t_BirthDate));
end;
/ 2 3 4 5 6 7 8
Trigger created.
Rodando o comando abaixo no primary, deixamos configurado para que a trigger possa ser disparada e alimente o standby:
SQL> exec dbms_ddl.set_trigger_firing_property( trig_owner => 'SOE', trig_name => 'RECONSTRUCT_PERSONS', property => dbms_ddl.apply_server_only, setting => TRUE);
PL/SQL procedure successfully completed.
Gerando archives no primary:
SQL> CONN / AS SYSDBA
Connected.
SQL> ALTER SYSTEM SWITCH LOGFILE;
System altered.
SQL> /
System altered.
SQL> /
System altered.
Confirmando que os objetos foram replicados para o standby database:
[oracle@fornix2 ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Tue Apr 6 04:23:21 2021
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
SQL> select count(*) from dba_objects where object_name in ('PERSONS', 'PERSONS_LOG');
COUNT(*)
----------
2
Para testar a replicação, vamos inserir 1 registro na tabela do primary:
[oracle@fornix1 ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Tue Apr 6 04:25:38 2021
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
SQL> insert into SOE.Persons (IdNumber, Department, Info)
values (1, 'Database' ,
SOE.Person('Bruno', 'Silva', trunc(sysdate))); 2 3
1 row created.
SQL> COMMIT;
Commit complete.
SQL> ALTER SYSTEM SWITCH LOGFILE;
System altered.
No logical standby, a tabela e conteúdo já foram replicados com sucesso:
SQL> select count(*) from SOE.persons;
COUNT(*)
----------
2
Obs: Este procedimento foi criado pelo senhor Ahmed Baraka (www.ahmedbaraka.com) e foi apenas reproduzido por mim em um laboratório pessoal para fins de aprendizado.