Bởi vì các deadlock xảy ra rất thường xuyên, có vẻ như một số luồng của ứng dụng đang bị khóa trong một khoảng thời gian dài.
Mỗi luồng trong ứng dụng sẽ sử dụng kết nối / kết nối cơ sở dữ liệu riêng của nó trong khi truy cập cơ sở dữ liệu, vì vậy theo quan điểm của cơ sở dữ liệu, hai luồng là hai ứng dụng khách khác nhau cạnh tranh cho các khóa cơ sở dữ liệu.
Nếu một chuỗi giữ các khóa trong một khoảng thời gian dài và có được chúng theo một thứ tự nhất định và một chuỗi thứ hai đi kèm với việc có được các khóa giống nhau nhưng theo một thứ tự khác, thì bế tắc nhất định xảy ra (xem tại đây để biết chi tiết về nguyên nhân thường xuyên bị tắc nghẽn này).
Ngoài ra, deadlock đang xảy ra trong các hoạt động đọc, có nghĩa là một số luồng cũng đang có được các khóa đọc. Điều này xảy ra nếu các chuỗi đang chạy các giao dịch trong REPEATABLE_READ
mức cô lập hoặc SERIALIZABLE
.
Để giải quyết vấn đề này, hãy thử tìm kiếm cách sử dụng của Isolation.REPEATABLE_READ
và Isolation.SERIALIZABLE
trong dự án, để xem liệu điều này có được sử dụng hay không.
Thay vào đó, hãy sử dụng READ_COMMITTED
mặc định mức cô lập và chú thích các thực thể bằng @Version
, để xử lý đồng thời bằng cách sử dụng khóa lạc quan
thay vào đó.
Cũng cố gắng xác định các giao dịch đang hoạt động lâu dài, điều này đôi khi xảy ra khi @Transactional
được đặt không đúng chỗ và kết thúc, chẳng hạn như việc xử lý toàn bộ tệp trong ví dụ về xử lý hàng loạt, thay vì thực hiện các giao dịch từng dòng một.
Đây là cấu hình log4j để ghi lại việc tạo / xóa trình quản lý thực thể và các giao dịch bắt đầu / cam kết / quay lại:
<!-- 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 >
- Bằng cách nào đó, tôi có thể thực hiện truy vấn cập nhật (JPA / Native) mà không cần phải khóa bảng qua @Transactional không?
Có thể cập nhật truy vấn thông qua truy vấn gốc hoặc JPQL .
- Bằng cách nào đó, tôi có thể tham gia phiên mà không sử dụng @Transactional không? Ví dụ:chuỗi được lập lịch cố gắng đọc trường Lazy trên Thực thể dẫn đến LazyInitializationException - không có phiên, nếu phương thức không được chú thích bằng @Transactional
Trong các phương thức không có @Transactional
, các truy vấn sẽ được thực thi trong trình quản lý thực thể của chính nó và chỉ trả về các thực thể tách rời, vì phiên của bạn bị đóng ngay lập tức sau khi truy vấn được chạy.
vì vậy các ngoại lệ khởi tạo lười biếng trong các phương thức không có @Transactional
bình thường. Bạn có thể đặt chúng thành @Transactional(readOnly=true)
nữa.