Mysql
 sql >> Database >  >> RDS >> Mysql

Ibernazione:trovato deadlock durante il tentativo di ottenere il blocco

Poiché i deadlock si verificano così frequentemente, sembra che alcuni thread dell'applicazione contengano blocchi per un periodo di tempo prolungato.

Ogni thread nell'applicazione utilizzerà la propria connessione/connessioni al database durante l'accesso al database, quindi dal punto di vista del database due thread sono due client distinti che competono per i blocchi del database.

Se un thread mantiene i lock per un lungo periodo di tempo e li acquisisce in un certo ordine, e un secondo thread arriva acquisendo gli stessi lock ma in un ordine diverso, è inevitabile che si verifichi un deadlock (vedi qui per i dettagli su questa frequente causa di deadlock).

Si verificano anche deadlock nelle operazioni di lettura, il che significa che anche alcuni thread stanno acquisendo blocchi di lettura. Ciò accade se i thread eseguono transazioni in REPEATABLE_READ livello di isolamento o SERIALIZABLE .

Per risolvere questo problema, prova a cercare gli usi di Isolation.REPEATABLE_READ e Isolation.SERIALIZABLE nel progetto, per vedere se viene utilizzato.

In alternativa, usa il READ_COMMITTED predefinito livello di isolamento e annota le entità con @Version , per gestire la concorrenza utilizzando il blocco ottimistico invece.

Prova anche a identificare le transazioni di lunga durata, questo accade a volte quando il @Transactional viene posizionato nel posto sbagliato e racchiude, ad esempio, l'elaborazione di un intero file nell'esempio di un'elaborazione batch, invece di eseguire transazioni riga per riga.

Questa è una configurazione log4j per registrare la creazione/cancellazione di gestori di entità e le transazioni iniziano/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 eseguire in qualche modo una query di aggiornamento (JPA/nativa) senza dover bloccare la tabella tramite @Transactional?

Le query di aggiornamento sono possibili tramite query native o JPQL .

  1. Posso in qualche modo entrare in sessione senza usare @Transactional? Ad esempio, il thread pianificato tenta di leggere il campo Lazy su Entity restituisce LazyInitializationException - nessuna sessione, se il metodo non è annotato con @Transactional

In metodi senza @Transactional , le query verranno eseguite nel proprio gestore di entità e restituiranno solo entità scollegate, poiché la sessione viene chiusa immediatamente dopo l'esecuzione della query.

quindi le eccezioni di inizializzazione pigra nei metodi senza @Transactional è normale. Puoi impostarli su @Transactional(readOnly=true) anche.