Browse By

Sincronismo bidirecional para SEQUENCE Oracle Golden Gate 11.1.1.1 (ou acima)?

Olá amigos,

Estou em alguns projetos de Golden Gate nessas ultimas semanas na qual um deles seria homologar a aplicação e o database em um ambiente bidirecional de sincronismo dos dados. Nesse tipo de arquitetura deve se tomar muitos cuidados antes de realmente aplica-los em produção e um dos problemas que me deparei nesse caso seria o sincronismo dos valores das sequences.

Em um ambiente unidirecional isso é muito tranquilo e o Oracle Golden Gate trata de uma maneira bem fácil, mas em um ambiente bidirecional ?

Fiquei um pouco desmotivado em saber que o Oracle Golden Gate 11.1 não suporta a replicação dos valores das sequences em ambiente bidirecional como mostra a documentação aqui.

   Para isso existem alguns métodos paliativos como criar sequences com valores diferentes em cada lado ex: (Source valores pares e Target valores ímpares) mas não é toda aplicação que vem com o código aberto para se fazer modificações onde a maioria dos ambientes que trabalho são “engessados”, então isso não resolve o meu problema.

Testando, testando e testando cada vez mais como se não acreditasse nisso (perfil de Dba. rs) consegui alcançar o objetivo fazendo algumas pequenas modificações utilizando somente o próprio Golden Gate, sem métodos externos, mas claro, isso acabou sendo uma alternativa devido ao ambiente não realizar grandes utilizações de sequences e a concorrência, acesso simultâneo ser quase nulo. Se fosse um ambiente que tivesse um grande acesso simultâneo e alta atualização das mesmas, dificilmente eu conseguiria utilizar esse método.

Vamos lá:

Seguindo a documentação abaixo:

http://docs.oracle.com/cd/E22355_01/doc.11111/e21406.pdf pagina 30

Mostra passo a passo da instalação com suporte a sequences.

Eu fiz algumas modificações, (passos 8 e 9 da documentação):

8 - GRANT EXECUTE on DDLuser.updateSequence TO DBLOGINuser; ( Executei em ambos = SOURCE e TARGET )
9 - GRANT EXECUTE on DDLuser.replicateSequence TO Replicatuser; ( Executei em ambos = SOURCE e TARGET )

Vamos aos testes:

Sobre o SOURCE:

SOURCE>create table CUSTOMERS
(CUSTOMER_ID number, CUSTOMER_NAME varchar2(30), CUSTOMER_REGISTRATION date, CURRDATE date);
Table created.

SOURCE>alter table CUSTOMERS
add constraint pkindx primary key (CUSTOMER_ID);

Table altered.

SOURCE>CREATE SEQUENCE CUSTOMER_ID_SEQ
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOMINVALUE
NOCYCLE
NOCACHE;

Sequence created.
SOURCE>select * from user_sequences;

SEQUENCE_NAME	 MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
----------
------------ - -
-----------
CUSTOMER_ID_SEQ 1 1.0000E+28	 1 N N	 0	 1 << Veja o numero atual da sequencia

Cheque no TARGET (Tudo foi replicado):

TARGET>desc CUSTOMERS
Name	 Null? Type
CUSTOMER_ID	 NOT NULL NUMBER
CUSTOMER_NAME	 VARCHAR2(30)
CUSTOMER_REGISTRATION	 DATE
CURRDATE	 DATE

TARGET>
TARGET>
TARGET>select * from user_sequences;

SEQUENCE_NAME	 MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
----------
------------ - -
-----------
CUSTOMER_ID_SEQ 1 1.0000E+28	 1 N N	 0	 1 << Mesmo numero que esta no SOURCE

Vamos inserir alguns registros no SOURCE:

SOURCE>
INSERT INTO CUSTOMERS SELECT CUSTOMER_ID_SEQ.NEXTVAL,
DBMS_RANDOM.STRING('P',DBMS_RANDOM.VALUE(1,30)),
(SYSDATE-1825)+DBMS_RANDOM.VALUE(1,1820),
CURRENT_TIMESTAMP FROM DUAL CONNECT BY LEVEL <= 100;

100 rows created.
SOURCE>commit;

Commit complete.

SOURCE>select * from user_sequences;

SEQUENCE_NAME	 MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
----------
------------ - -
-----------
CUSTOMER_ID_SEQ 1 1.0000E+28	 1 N N	 0	 101 << Numero da sequence foi incrementado

Cheque no TARGET :

TARGET>SELECT COUNT(*) FROM CUSTOMERS;

COUNT(*)
100

TARGET>select * from user_sequences;

SEQUENCE_NAME	 MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
----------
------------ - -
-----------
CUSTOMER_ID_SEQ 1 1.0000E+28	 1 N N	 0	 101 << O Numero também foi incrementado (Ate aqui sem segredos)

Agora, vamos inserir registros no TARGET para replicar no SOURCE:

TARGET>
INSERT INTO CUSTOMERS SELECT CUSTOMER_ID_SEQ.NEXTVAL,
DBMS_RANDOM.STRING('P',DBMS_RANDOM.VALUE(1,30)),
(SYSDATE-1825)+DBMS_RANDOM.VALUE(1,1820),
CURRENT_TIMESTAMP FROM DUAL CONNECT BY LEVEL <= 100;
100 rows created.
TARGET>commit;

Commit complete.
TARGET>SELECT COUNT(*) FROM CUSTOMERS;

COUNT(*)
200

TARGET>select * from user_sequences;

SEQUENCE_NAME	 MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
----------
------------ - -
-----------
CUSTOMER_ID_SEQ 1 1.0000E+28	 1 N N	 0	 201 << Logicamente o numero foi incrementado.

Checando no SOURCE:

SOURCE>SELECT COUNT(*) FROM CUSTOMERS;

COUNT(*)
200

SOURCE>select * from user_sequences;

SEQUENCE_NAME	 MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER
----------
------------ - -
-----------
CUSTOMER_ID_SEQ 1 1.0000E+28	 1 N N	 0	 201 << voila.. O NUMERO TAMBÉM FOI ATUALIZADO.
SOBRE TARGET:

TARGET>drop sequence CUSTOMER_ID_SEQ;

Sequence dropped.

TARGET>select * from user_sequences;

no rows selected
SOBRE SOURCE:

SOURCE>select * from user_sequences;

no rows selected

Com isso vemos que a documentação diz que o Golden Gate não suporta o sincronismo bidirecional de sequence nessa release 11.1.1, mas eu acredito que nas próximas ele irá, pois no nosso teste foi usado somente a própria ferramenta sem qualquer modificação a nível de código ou estrutura dos objetos da aplicação.

“Não esqueçam de colocar o parametro SEQUENCE em ambos extract e pump sobre ambos os lados.”

Post in english:
https://forums.oracle.com/forums/thread.jspa?messageID=10152874&#10152874

Forte abraço

Leave a Reply

Your email address will not be published. Required fields are marked *