Re:Controle de transação entre duas bases distintas

Bom,

vamos começar um Brainstorming aqui então :slight_smile:

Se o seu processo Batch for em Java, pode fazer de forma “sincronizada”, em cima de uma chave comum nas duas tabelas.

Você cria uma chave do tipo TRANSACTIONID. E o Batch inicia uma Thread para cada transação.

Não poderia ser assim?

[quote=osmio]Boa tarde galera!

To passando por sérios apuros aqui!! :smiley:
Gostaria de algumas sugestões e opiniões de vocês.

O problema é o seguinte:
Tenho duas bases de dados distintas e um processo batch que captura alguns dados da base X, consolida e insere na base Y.

Bom, quanto a isso, nenhum problema, desde que as duas bases estejam no ar e operando normalmente.
O problema maior é que eu tenho que garantir a consistência dos dados em ambos os lados, ou seja, eu pego alguns registros na base X e insiro na base Y e como resultado a inserção na base Y, eu atualizo alguns campos na base X.

Como eu poderia garantir a consistência dessas transações, uma vez que dependo do acesso a rede e de máquinas e bases diferentes?

At
[/quote]

Se o processo for feito em uma tacada só, de uma vez, basta controlar com flags… do tipo erro = false; (putz) rsss…

Se o primeiro processo de leitura der tudo certo, erro = false; senao erro = true; e se erro = true, aborta tudo…

Se o segundo passo do processo (gravar na base Y) der certo erro = false; senao erro = true e aborta o ultimo passo.

Entendeu ?

Vc não poderia fazer transações compensatórias?

[quote=osmio]Bom, vou tentar dar uma resposta aqui que compense todas as opiniões:

O que acontece hoje:

Se o commit na base Y for realizado corretamente, eu comito na base X, se o comiit na base X for executado corretamente, tudo foi perfeito, lindo, maravilha, mantive meu emprego!!!
:smiley:

Vamos fazer algumas suposições do mundo real:

if (baseY.commit() == true) { baseX.commit(); } else { baseY.rollback(); baseX.rollback(); }
Nesse caso OK, o commit na base X espera a garantia de que o commit na base Y tenha sido feito. Caso o commit na base Y nao tenha sido efetuado, eu utilizo o rollback() de ambas as bases, garantindo assim a consistência.

Agora, imagine a situação:
commit() na base Y efetuado corretamente, e o commit() na base X desceu o penhasco com uma SQLException nas costas!!!

O que fazer nesse caso?
poderia dar o rollback() em ambos os casos como feito anteriormente, porém a base Y já efetuou o commit(), e queiramos ou não isso é irremediável!!!

O que fazer agora?
Tenho um monte de registros inconsistentes na base Y, e isso prezados, não é bom pra ninguém!!!

At.[/quote]

Se você deu o commit na base Y chora !!! Com o controle transacional “clássico” o dado já está lá… você poderia logar tudo o que foi feito em Y e utilizar o recurso de “desfazimento”, mas ai teria que ser feito na mão…

Tem um exemplo de como isso poderia ser feito?[/quote]

Acompanha essa Thread e pesquisa um pouco.
http://www.guj.com.br/posts/list/30/23150.java

Nunca implementei transações compensatórias de fato, portanto posso dar pouco apoio técnico, mas basta ter uma fonte… :wink:

Acho que no seu caso a melhor opção seria JTA com Two Phase Commit.
Nunca precisai implementar, portanto não sei o nivel de trabalho/dificuldade, mas pelo que ja li a respeito deve resolver o seu problema.

[]´s

São duas tabelas no mesmo banco? É oracle?

[quote]
InsanelyTotalMac

if (baseY.commit() == true) { baseX.commit(); } else { baseY.rollback(); baseX.rollback(); } [/quote]

só para não ficar estranho, não há necessidade de comparar valores booleanos

if (baseY.commit()) {
    baseX.commit();
} else {
    baseY.rollback();
    baseX.rollback();
}

[quote=bruxel][quote]
InsanelyTotalMac

if (baseY.commit() == true) { baseX.commit(); } else { baseY.rollback(); baseX.rollback(); } [/quote]

só para não ficar estranho, não há necessidade de comparar valores booleanos

if (baseY.commit()) { baseX.commit(); } else { baseY.rollback(); baseX.rollback(); } [/quote]

Acho que ele não pode fazer desta maneira porque precisa garantir que as duas funcionarão ou nenhuma funcionará. Não pode ocorrer casos em que Y funcione e X não. Mas issio ele pode confirmar melhor.

[quote=osmio]Boa tarde galera!

To passando por sérios apuros aqui!! :smiley:
Gostaria de algumas sugestões e opiniões de vocês.

O problema é o seguinte:
Tenho duas bases de dados distintas e um processo batch que captura alguns dados da base X, consolida e insere na base Y.

Bom, quanto a isso, nenhum problema, desde que as duas bases estejam no ar e operando normalmente.
O problema maior é que eu tenho que garantir a consistência dos dados em ambos os lados, ou seja, eu pego alguns registros na base X e insiro na base Y e como resultado a inserção na base Y, eu atualizo alguns campos na base X.

Como eu poderia garantir a consistência dessas transações, uma vez que dependo do acesso a rede e de máquinas e bases diferentes?

[/quote]

AO Transaction Manager importa um pepino se são máquinas ou bases diferentes.
O que vc faz é colocar o transaction manager a funcionar ( se usar um servidor JEE ele já está funcionando)
Abrea transação, le de X, grava em Y, le de Y grava em X e commita a transação. Simples assim.

Todo o trabalho de controle é feito pelo transaction manager.

Se vc não tem um transaction manager, a solução é arranjar um. O JTOM é uma boa tem até um tutorial de como instalalo no tomcat sem ser preciso servidor de aplicação, mas a melhor opção é realmente usar um servidor de aplicação que é para isso que eles servem.

[quote=osmio][quote=sergiotaborda]
AO Transaction Manager importa um pepino se são máquinas ou bases diferentes.
O que vc faz é colocar o transaction manager a funcionar ( se usar um servidor JEE ele já está funcionando)
Abrea transação, le de X, grava em Y, le de Y grava em X e commita a transação. Simples assim.

Todo o trabalho de controle é feito pelo transaction manager.

Se vc não tem um transaction manager, a solução é arranjar um. O JTOM é uma boa tem até um tutorial de como instalalo no tomcat sem ser preciso servidor de aplicação, mas a melhor opção é realmente usar um servidor de aplicação que é para isso que eles servem.[/quote]

Qual a porcentagem de garantias que eu teria utilizando um Transaction Manager??

Porque, por exemplo, eu tenho uma pequena solução que contorna alguns possíveis erros. Isso me dá uma margem de aproximadamente 92% de garantias de que as transações (em ambos os lados) serão efetuadas.

8% de possibilidade de acontecer alguma coisa que não deveria, para mim é uma margem absurdamente grande.

Utilizando JTA ou o próprio JTOM (citado acima) eu conseguiria aumentar em quanto os meus 92% de garantia??

At.[/quote]

?? 92% de garantia ? como vc chega nesse numero ?

Independentemente disso, 92% ou zero é a mesma coisa.
O Transaction Manager da JTA ( da qual o JTOM é uma implementação) lhe dá 100% garantia. Não poderia ser de outra forma já que as transações do JTA são ACID . A letra importante aqui é A (Atómica) que significa : ou faz tudo, ou não faz nada.
92% não faz nenhum sentido. Isso significaria que , para começo de conversa as suas transações não são atomicas. Se elas não são atomicas, mais vale nem usar transação. 92% significaria que faz quase tudo , mas o que não faz é suficiente para destruir o sistema. Nem que fosse 0.000…1%

Não faz sentido falar de porcentagem num ambiente ACID:

Atomico : ou tudo ou nada. Não ha meia alteração , nem 87% de alteração.
Consistente : o estado do sistema, antes, durante e depois da transação, independente se deu commit ou roolback é consistente, i.e. não se perde informação e não ha informação “lixo” sendo gerada.
Isolado: uma transação não interfere com a outra.
Duravél: se a transação altera o estado do sistema, o sistema permanece nesse estado.

O ponto é que isso é irrelevante para o controle de transação… Se ha um problema na comunicação a transação simplesmente é abortada e o programa informado. Ele pode repetir a ação mais tarde.

A disponibilidade da conexão e do banco são fatores importantes, mas para a aplicação como um todo, não para o controle de transação.

Em teoria, Two Phase Commit resolve exatamente o seu problema.
Se o seu processo realmente é batch, sem nenhum estresse com usuários alterando os dados durante o processo, Two Phase é o mais simples de implementar, e não precisa usar nenhum framework. Já está implementado no driver JDBC.
Dá uma pesquisa por XATransaction. O Oracle e o DB2 eu sei que suportam isso.
E é 100% de certeza que eles garantem ACID =D
A não ser que tiver bugs no banco, mas dai não há milagre que resolva a parada.
[edit]
Two Phase só faz o commit quando as duas bases dão o OK final.
[/edit]

Boa tarde galera!

To passando por sérios apuros aqui!! :smiley:
Gostaria de algumas sugestões e opiniões de vocês.

O problema é o seguinte:
Tenho duas bases de dados distintas e um processo batch que captura alguns dados da base X, consolida e insere na base Y.

Bom, quanto a isso, nenhum problema, desde que as duas bases estejam no ar e operando normalmente.
O problema maior é que eu tenho que garantir a consistência dos dados em ambos os lados, ou seja, eu pego alguns registros na base X e insiro na base Y e como resultado a inserção na base Y, eu atualizo alguns campos na base X.

Como eu poderia garantir a consistência dessas transações, uma vez que dependo do acesso a rede e de máquinas e bases diferentes?

At

Bom, vou tentar dar uma resposta aqui que compense todas as opiniões:

O que acontece hoje:

Se o commit na base Y for realizado corretamente, eu comito na base X, se o comiit na base X for executado corretamente, tudo foi perfeito, lindo, maravilha, mantive meu emprego!!!
:smiley:

Vamos fazer algumas suposições do mundo real:

if (baseY.commit() == true) { baseX.commit(); } else { baseY.rollback(); baseX.rollback(); }
Nesse caso OK, o commit na base X espera a garantia de que o commit na base Y tenha sido feito. Caso o commit na base Y nao tenha sido efetuado, eu utilizo o rollback() de ambas as bases, garantindo assim a consistência.

Agora, imagine a situação:
commit() na base Y efetuado corretamente, e o commit() na base X desceu o penhasco com uma SQLException nas costas!!!

O que fazer nesse caso?
poderia dar o rollback() em ambos os casos como feito anteriormente, porém a base Y já efetuou o commit(), e queiramos ou não isso é irremediável!!!

O que fazer agora?
Tenho um monte de registros inconsistentes na base Y, e isso prezados, não é bom pra ninguém!!!

At.

Tem um exemplo de como isso poderia ser feito?

[quote=kinow]Bom,

vamos começar um Brainstorming aqui então :slight_smile:

Se o seu processo Batch for em Java, pode fazer de forma “sincronizada”, em cima de uma chave comum nas duas tabelas.

Você cria uma chave do tipo TRANSACTIONID. E o Batch inicia uma Thread para cada transação.

Não poderia ser assim?[/quote]

Essa é “mais-ou-menos” a maneira como está implementada a solução hoje. O problema todo esta na consolidação (o processamento batch) ser realizado anteriormente à obtenção do TID.

E confesso-lhe com segurança que isso esta errado, muito errado!!!
rsrs

At.

[quote=InsanelyTotalMac]
Se você deu o commit na base Y chora !!! Com o controle transacional “clássico” o dado já está lá… você poderia logar tudo o que foi feito em Y e utilizar o recurso de “desfazimento”, mas ai teria que ser feito na mão… [/quote]

Ai é que esta mais um problema.
Poderia ter uma rotina de “exclusão” dos registros inseridos. Porém, não tenho garantia se o registro foi, de fato, inserido ou se foi atualizado.

Isso porque em tempo de execução ele verifica se já existe um registro compatível com o que esta sendo inserido. Se existe, atualiza. Se não existe, insere.

Portanto, a técnica de reversão fica muito mais complicada de se implementar do que imaginar.

At.

[quote=bruxel]

só para não ficar estranho, não há necessidade de comparar valores booleanos[/quote]

:wink:
Opa! To sabendo disso desde os primordios!!!

Coloquei assim pra ficar bem claro o que eu estava detalhando.

At.

[quote=kinow]
Acho que ele não pode fazer desta maneira porque precisa garantir que as duas funcionarão ou nenhuma funcionará. Não pode ocorrer casos em que Y funcione e X não. Mas issio ele pode confirmar melhor.[/quote]

Exatamente isso!
Ou faz tudo, ou não faz nada.

8 ou 80!!