Prezados senhores(as)

Antecipadamente peço desculpas pela extensão da descrição do problema, mas é na 
tentativa de ser o mais claro possível.

Estou trabalhando com um sistema legado que possui 3 tabelas de estoque 
desnormalizadas, da seguinte forma (as chaves primárias compostas estão 
identificadas pela #):
- Tabela ESTOQUE 
 # Id, 
 # Empresa, 
 # DataFabricacao, 
 # Valor, 
   Qtd
   
- Tabela SITUACAO_EST
 # Sit_Id, 
 # Sit_Empresa, 
 # Sit_DataFabricacao, 
 # Sit_Valor, 
 # Situacao, 
   Qtd

- Tabela CLASSE_SIT_EST
 # Cl_Sit_Id, 
 # Cl_Sit_Empresa, 
 # Cl_Sit_DataFabricacao, 
 # Cl_Sit_Valor, 
 # Cl_Situacao, 
 # Classe,
   Qtd
 
Um exemplo: podemos ter:

Na tabela ESTOQUE, o seguinte material (uma camisa, cuja Id = CAM01):
 - id = CAM01, empresa = ABC, data = 01/01/2005, valor = 10, qtd = 500

Na tabela SITUACAO_EST, o material acima estaria distribuído assim:
 - CAM01, ABC, 01/01/2005, 10, situacao = DISPONIVEL, 300
 - CAM01, ABC, 01/01/2005, 10, TRANSITO, 200

Na tabela CLASSE_SIT_EST, o material acima estaria distribuído assim:
 - CAM01, ABC, 01/01/2005, 10, DISPONIVEL, classe = 1, 250
 - CAM01, ABC, 01/01/2005, 10, DISPONIVEL, 2, 50
 - CAM01, ABC, 01/01/2005, 10, TRANSITO, 1, 200

Ou seja, o material id = CAM01, empresa = ABC, data = 01/01/2005, valor = 10 
tem que somar 500 em cada uma das tabelas.

Quando uma GUIA é emitida, o material sai da situação DISPONIVEL e passa para 
TRANSITO. Assim, no exemplo acima, existe uma guia em aberto com 200 camisas.
Ao QUITAR uma guia, a quantidade em TRANSITO é zerada e a quantidade 
correspondente é abatida na tabela ESTOQUE. Ou seja, ao quitar a guia, serão 
zeradas as quantidades em trânsito nas tabelas CLASSE_SIT_EST e SITUACAO_EST e 
será abatido 200 da quantidade na tabela ESTOQUE.

Isso é controlado somente por uma rotina executada ao ser pressionado um botão 
em um FORM (ação WHEN BUTTON PRESSED - estamos utilizando FORMS 6i e banco 
8.1.7). 

Nesta rotina é feito um SELECT FOR UPDATE e em seguida um UPDATE para cada uma 
das 3 tabelas acima. Em nenhum momento é executada uma INCLUSÃO ou ALTERAÇÃO em 
apenas uma das tabelas (mesmo na inclusão de novo estoque, a rotina sempre 
trabalha com as 3 tabelas). E no final da rotina, um COMMIT.

Bem, o problema é o seguinte: ocasionalmente essas tabelas estão ficando 
inconsistentes (por exemplo, a soma das quantidade na tabela SITUACAO_EST não 
confere com a soma das quantidades das outras duas.

Criei, na tentativa de encontrar o problema, através de trigger AFTER INSERT, 
DELETE OR UPDATE nas tabelas acima, uma "auditoria" em uma outra tabela 
auxiliar. Assim, cada vez que é executada uma das operações acima eu gravo 
nesta outra tabela todos os valores das linhas afetadas. Com isso, eu 
verifiquei uma situação que me deixou bastante surpreso.

Usando os exemplos acima, ao quitar uma guia, ficaram na tabela auditoria os 
seguintes registros:

UPDATE em CLASSE_SIT_EST, abatendo 200 da QTD da linha CAM01, ABC, 01/01/2005, 
10, TRANSITO, 1, 200; (deixou com zero)
UPDATE em SITUACAO_EST, abatendo 200 da QTD da linha linha CAM01, ABC, 
01/01/2005, 10, TRANSITO, 200; (deixou com zero)
UPDATE em ESTOQUE, abatendo 200 da QTD da linha linha CAM01, ABC, 01/01/2005, 
10, 500; (deixou com 300)

Até aí, tudo bem. Em, seguida
UPDATE em CLASSE_SIT_EST, abatendo X da QTD da linha referente ao próximo item 
da guia (também OK)

*** E aí a surpresa: NOVAMENTE a linha
UPDATE em ESTOQUE, abatendo 200 da QTD da linha CAM01, ABC, 01/01/2005, 10, 
500; (ou seja, NOVAMENTE RETIRANDO 200 daquele item)

Por isso as quantidade acabam ficando inconsistentes. E pude ver também que 
isso não ocorre sempre com a mesma tabela, em outras situações ocorreu com 
algum das outras duas.

Essas tabelas fazem parte de um grupo de replicação assíncrona. Pesquisando 
sobre o assunto (embora eu não seja DBA tive que correr atrás), li que a 
replicação não garante uma serializabilidade das transações, podendo ocorrer o 
caso de transações iniciadas depois acabarem antes de outras transações mais 
antigas, por isso devendo ser monitorada constantemente.

Antigamente a replicação nesse sistema era Multimaster, e como, revendo o 
projeto, vimos que isso não era necessário, foi refeito o esquema da 
replicação, alterando-as para MASTER na filial correspondente e criando apenas 
MATERIALIZED VIEW na matriz.
Isso diminuiu bastante a ocorrência deste problema, o que me leva a pensar que 
de alguma forma a replicação Multimaster estava causando isso. 

Mas hoje, mesmo com a tabela fisicamente apenas na própria filial, o problema 
ainda ocorre (bem menos, é verdade, mas ocorre).

Gostaria de saber dos companheiros se alguém já passou por isso, se sabe pelo 
menos em teoria se isso pode realmente ser causado pelo processo da replicação, 
ou se existiria algum outro motivo que pudesse estar causando essa anomalia.

Minha idéia é que, no exemplo acima, se ocorresse algum erro ao alterar o 
estoque do segundo item da guia, deveria ocorrer um ROLLBACK desfazendo as 
alterações ocorridas no primeiro item, e NUNCA refazer uma operação já 
concluída.

Agradeço muito qualquer "luz" que me seja fornecida neste caso. Faço parte da 
equipe de desenvolvimento, já levei o caso aos nossos DBA,s, mas até agora 
nenhuma resposta plausível me foi fornecida. 

Caso seja necessária mais alguma informação, estou à completa disposição.

Marcel


[As partes desta mensagem que não continham texto foram removidas]



______________________________________________________________________

Histórico: http://www.mail-archive.com/oracle_br@yahoogrupos.com.br/
Falar com os Moderadores:([EMAIL PROTECTED])
Dorian Anderson Soutto - Fernanda Damous - Alisson Aguiar 
______________________________________________________________________ 
Links do Yahoo! Grupos

<*> Para visitar o site do seu grupo na web, acesse:
    http://br.groups.yahoo.com/group/oracle_br/

<*> Para sair deste grupo, envie um e-mail para:
    [EMAIL PROTECTED]

<*> O uso que você faz do Yahoo! Grupos está sujeito aos:
    http://br.yahoo.com/info/utos.html

 


Responder a