OutOfMemory e Corrupção de Banco de Dados

Olá pessoal!

procurei por aqui e no Google e não encontrei nada a respeito, então recorro a vocês.
Tenho uma aplicação java que dá OutOfMemory. Até aí, o problema é conhecido e estou trabalhando nisso. No pior caso, enquanto não consigo fazer uma uso otimizado da memória (ou detectar o meu ponto de vazamento), acabo reiniciando a aplicação, o que me permite utilizar de novo por algum tempo.
O problema é que quando ocorre OutOfMemory, os dados da minha aplicação ficam inconsistente. Isso inclui dados que já estavam consistentes antes, ou seja, a aplicação corrompe dados que já haviam sido comitados.

Exemplo: cadastrei um funcionário. Consultei o funcionário e tudo está certo (inclusive consultando no banco via SQL). Em seguida, vou cadastrar os filhos do funcionário e acaba dando OutOfMemory. Quando reinicio a aplicação, não apenas os filhos possuem dados errados, como também o funcionário.

A pergunta é: o gerenciamento de memória da VM (usado junto com Hibernate, Spring e Oracle) podem provocar esse erro, ou a minha aplicação possui um bug que eu ainda não consegui encontrar?

Desde já agradeço a ajuda!
Takeda

eu tambem tenho nisso numa aplicacao. se eu deixar 20 dias sem reiniciar, da OOm e o MALDITO tomcat loga o Error e ENGOLE. sendo que na documentacao esta BEM explicitado que voce nao deve segurar a execucacao ao ocorrer um OOM.

voce deve dar um jeito de nao engulir a OOM, no primeiro momento que ela ocorrer ela deve subir e em algum lugar voce desliga a aplicacao.

use um pofiler pra saber o que voce esta segurando que nao era pra segurar.

Voce deveria focar em resolver o OOM primeiro, ao inves de focar nos problemas de dados corrompidos.
Talvez uma coisa nem esteja associada a outra, mas resolver o OOM deveria ser a sua prioridade.

Rafael

Isso é teoricamente possivel de acontecer dependendo da qualidade do driver o comportamento padrão do banco no caso de transações interrompidas sem commit/rollback.

O driver pro teu banco pode estar fazendo burradas quando um OOM acontece dentro dele, procure no google a respeito.

Ou então pode estar ocorrendo da transação estar sendo interrompida antes do commit/rollback e o teu RDBMS estar dando commit para você.

Cenario:


1. begin trs
2. update xxx
    insert xxx
2.1. A JVM é terminada 
3. ok ? commit else rollback

Fora isso não posso sugerir muito mais sem maiores informações sobre o ambiente.

Se não tiver outra maneira, faça o seguinte:

try {
  commited = false;
  ....
  commit();
  commited = true;
} catch(OutOfMemoryError e) {
  doMemHedge();
} finally {
   if(!commited) rollback();
}

static byte[] hedge = new byte[1000 * 100];
void doMemHedge() {
  hedge = null;
  System.gc();
}

Esse exemplo simplifica bastante a coisa por que não leva em conta a reaquisição de memoria de hedging nem JVMs que usam areas distintas para tamanhos diferentes de objetos.

Parceiro,

minha aplicação é feita com (Spring + Hibernate + Oracle) também.
No ambiente do cliente ocorre muito outOfMemory, porém nunca houve problema de corrupção de dados ou falha no controle de transação.