Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como posso desbloquear automaticamente tabelas no Oracle após um determinado tempo?


Primeiramente, bloquear uma tabela não impedirá que outra sessão emita SELECT declarações contra os dados.

Na Sessão 1, se eu bloquear a tabela
SQL> lock table foo in exclusive mode;

Table(s) Locked.

Eu posso então iniciar a Sessão 2 e consultar todos os dados que eu gostaria
SQL> select * from foo;

      COL1
----------
         1
         1

No Oracle, os gravadores não bloqueiam os leitores, portanto, você nunca pode impedir que outra sessão consulte os dados em uma tabela.

Parece que o que você está tentando implementar é um bloqueio pessimista. Nesse caso, em vez de bloquear a tabela, você faz um SELECT FOR UPDATE que bloqueia a entrada específica que você pretende processar. Contanto que todas as outras sessões também tentem fazer um SELECT FOR UPDATE (dependendo da versão do Oracle, potencialmente adicionando o SKIP LOCKED qualificador e/ou o WAIT qualificador). Isso bloqueia a linha específica que você está processando e permite que a segunda sessão selecione uma linha diferente ou limite o tempo limite ou descubra que não há linhas para processar, dependendo das especificidades da implementação. Isso não envolve bloquear a tabela.

A única maneira de um bloqueio ser liberado é que a sessão que o adquiriu o libere (geralmente encerrando a transação) ou que a sessão que o adquiriu seja encerrada. Se o aplicativo cliente ainda estiver em execução, mas não estiver fazendo nada para liberar o bloqueio ou encerrar a sessão, o bloqueio será mantido indefinidamente. Um DBA precisaria matar explicitamente a sessão, deixando a transação reverter e liberando o bloqueio para que o sistema se movesse novamente. Se o aplicativo cliente parar de ser executado ou, pelo menos, parar de responder (ainda não entendi exatamente qual cenário de falha você está discutindo), é possível que habilitar a detecção de conexão morta (DCD) por meio do parâmetro 'SQLNET.EXPIRE_TIME' no nível do banco de dados faria com que o banco de dados determinasse que o cliente não responde e encerrasse automaticamente a sessão, revertendo a transação e liberando o bloqueio.

No entanto, se houver várias sessões processando dados, geralmente é preferível usar alguma forma de bloqueio otimista. Caso contrário, você está projetando um sistema que inevitavelmente precisará que o DBA encontre e elimine sessões com urgência para que os usuários de negócios voltem a trabalhar e isso exigirá cada vez mais intervenção quanto mais ocupado estiver. Isso não é algo que os DBAs gostem de fazer e não é algo que os usuários de negócios gostem de reclamar. Um esquema de bloqueio otimista simples seria algo como
  • Selecione uma chave para processar e algum tipo de data que indique a última vez que a linha foi atualizada.
  • Atualize uma coluna de status para "processando" para que outras sessões não tentem processar a mesma linha.
  • Processar a entrada em seu aplicativo
  • Ao terminar o processamento, atualize os dados usando a chave e o horário que você selecionou na primeira etapa. Se você atualizar 1 linha, saberá que nenhuma outra sessão modificou os dados em questão desde que você os selecionou. Se você atualizar 0 linhas, saberá que alguma outra sessão modificou os dados desde que você os selecionou.

Com esse tipo de arquitetura, é relativamente fácil consultar o banco de dados para ver quais linhas estão sendo processadas e, por exemplo, ter um trabalho que defina a coluna de status de volta para "não processado" após algum período de tempo se o cliente não tiver finalizado. É realmente fácil para outras sessões escolher uma linha diferente para processar. E é relativamente seguro se, por exemplo, o aplicativo congelar por algumas horas e depois se recuperar, já que ele descobre que, depois de concluir o processamento, alguma outra sessão já reprocessou a linha.