Тъй като блокирането се случва толкова често, изглежда, че някои от нишките на приложението държат заключвания за продължителен период от време.
Всяка нишка в приложението ще използва своя собствена връзка/връзки към базата данни, докато осъществява достъп до базата данни, така че от гледна точка на базата данни двете нишки са два различни клиента, които се конкурират за заключвания на база данни.
Ако дадена нишка държи брави за продължителен период от време и ги придобива в определен ред, а втора нишка се появява, придобивайки същите ключалки, но в различен ред, задължително ще възникне застой (вижте тук за подробности относно тази честа причина за блокиране).
Също така се появяват блокирания при операции за четене, което означава, че някои нишки също придобиват заключвания за четене. Това се случва, ако нишките изпълняват транзакции в REPEATABLE_READ
ниво на изолация или SERIALIZABLE
.
За да разрешите това, опитайте да потърсите употреби на Isolation.REPEATABLE_READ
и Isolation.SERIALIZABLE
в проекта, за да видите дали това се използва.
Като алтернатива използвайте READ_COMMITTED
по подразбиране ниво на изолация и анотирайте обектите с @Version
, за обработка на паралелност с помощта на оптимистично заключване
вместо това.
Също така се опитайте да идентифицирате дългосрочни транзакции, това се случва понякога, когато @Transactional
се поставя на грешно място и обвива например обработката на цял файл в примера на пакетна обработка, вместо да извършва транзакции ред по ред.
Това е конфигурация на log4j за регистриране на създаването/изтриването на мениджъри на обекти и започване/завършване/връщане на транзакции:
<!-- 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 >
- Мога ли по някакъв начин да изпълня заявка за актуализиране (или JPA/Native), без да се налага да заключвам таблицата чрез @Transactional?
Заявките за актуализиране са възможни чрез естествени заявки или JPQL .
- Мога ли по някакъв начин да вляза в сесия, без да използвам @Transactional? Например, насрочената нишка се опитва да прочете полето Lazy на Entity, се отдава на LazyInitializationException - няма сесия, ако методът не е анотиран с @Transactional
В методи без @Transactional
, заявките ще се изпълняват в неговия собствен мениджър на обекти и ще връщат само обособени обекти, тъй като сесията се затваря веднага след изпълнението на заявката.
така че изключенията за мързелива инициализация в методи без @Transactional
е нормално. Можете да ги зададете на @Transactional(readOnly=true)
също.