Protože k zablokování dochází tak často, vypadá to, že některá vlákna aplikace drží zámky po delší dobu.
Každé vlákno v aplikaci bude při přístupu k databázi používat své vlastní databázové připojení/připojení, takže z pohledu databáze jsou dvě vlákna dva odlišní klienti, kteří soutěží o uzamčení databáze.
Pokud vlákno drží zámky po delší dobu a získává je v určitém pořadí a přijde druhé vlákno, které získává stejné zámky, ale v jiném pořadí, nutně dojde k uváznutí (viz zde podrobnosti o této časté příčině zablokování).
Při operacích čtení také dochází k uváznutí, což znamená, že některá vlákna získávají také zámky čtení. K tomu dochází, pokud vlákna provádějí transakce v REPEATABLE_READ
úroveň izolace nebo SERIALIZABLE
.
Chcete-li to vyřešit, zkuste vyhledat použití Isolation.REPEATABLE_READ
a Isolation.SERIALIZABLE
v projektu, abyste zjistili, zda se používá.
Jako alternativu použijte výchozí READ_COMMITTED
úroveň izolace a označte entity pomocí @Version
, ke zpracování souběžnosti pomocí optimistického zamykání
místo toho.
Zkuste také identifikovat dlouho běžící transakce, to se někdy stává, když je @Transactional
je umístěn na nesprávném místě a zabalí například zpracování celého souboru do příkladu dávkového zpracování, místo aby transakce prováděl řádek po řádku.
Toto je konfigurace log4j pro protokolování vytváření/mazání správců entit a zahájení/potvrzení/vrácení transakcí:
<!-- 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 >
- Mohu nějak provést aktualizační dotaz (buď JPA/Native), aniž bych musel zamykat tabulku přes @Transactional?
Aktualizační dotazy jsou možné prostřednictvím nativních dotazů nebo JPQL .
- Mohu se nějak dostat do relace bez použití @Transactional? Například plánované vlákno se pokusí přečíst pole Lazy na Entity výnosy LazyInitializationException – žádná relace, pokud metoda není označena @Transactional
V metodách bez @Transactional
, budou dotazy prováděny v jeho vlastním správci entit a vrátí pouze oddělené entity, protože tato relace je uzavřena ihned po spuštění dotazu.
takže výjimky z líné inicializace v metodách bez @Transactional
je normální. Můžete je nastavit na @Transactional(readOnly=true)
také.