Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Hibernate:Deadlock encontrado ao tentar obter o bloqueio


Como os deadlocks acontecem com tanta frequência, parece que alguns dos threads do aplicativo estão mantendo bloqueios por um longo período de tempo.

Cada thread no aplicativo usará sua própria conexão/conexões de banco de dados ao acessar o banco de dados, portanto, do ponto de vista do banco de dados, dois threads são dois clientes distintos que competem por bloqueios de banco de dados.

Se um encadeamento retém bloqueios por um longo período de tempo e os adquire em uma determinada ordem, e um segundo encadeamento vier adquirindo os mesmos bloqueios, mas em uma ordem diferente, ocorrerá um deadlock (consulte aqui para obter detalhes sobre essa causa frequente de deadlock).

Também estão ocorrendo deadlocks em operações de leitura, o que significa que alguns threads também estão adquirindo bloqueios de leitura. Isso acontece se os encadeamentos estiverem executando transações em REPEATABLE_READ nível de isolamento ou SERIALIZABLE .

Para resolver isso, tente pesquisar os usos de Isolation.REPEATABLE_READ e Isolation.SERIALIZABLE no projeto, para ver se isso está sendo usado.

Como alternativa, use o padrão READ_COMMITTED nível de isolamento e anote as entidades com @Version , para lidar com a simultaneidade usando bloqueio otimizado em vez de.

Tente também identificar transações de longa duração, isso acontece às vezes quando o @Transactional é colocado no lugar errado e envolve, por exemplo, o processamento de um arquivo inteiro no exemplo de um processamento em lote, em vez de fazer transações linha por linha.

Esta é uma configuração do log4j para registrar a criação/exclusão de gerenciadores de entidade e transações começam/commit/rollback:
   <!-- spring entity manager and transactions -->
<logger name="org.springframework.orm.jpa" additivity ="false">
    <level value="debug" />
    <appender-ref ref="ConsoleAppender" />
</logger >
<logger name="org.springframework.transaction" additivity ="false">
    <level value="debug" />
    <appender-ref ref="ConsoleAppender" />
</logger >
  1. Posso de alguma forma executar a consulta de atualização (JPA/Native) sem ter que bloquear a tabela via @Transactional?

As consultas de atualização são possíveis por meio de consultas nativas ou JPQL .
  1. Posso de alguma forma entrar na sessão sem usar @Transactional? Por exemplo, o thread agendado tenta ler o campo Lazy em Entity produz LazyInitializationException - sem sessão, se o método não estiver anotado com @Transactional

Em métodos sem @Transactional , as consultas serão executadas em seu próprio gerenciador de entidades e retornarão apenas entidades desvinculadas, pois a sessão é fechada imediatamente após a execução da consulta.

então as exceções de inicialização lenta em métodos sem @Transactional é normal. Você pode configurá-los para @Transactional(readOnly=true) também.