Transaction_And_Concurrency
1. Transaction Isolation Levels
Trong Spring Data JPA, chúng ta có thể kiểm soát mức độ cách ly của các giao dịch bằng cách sử dụng các Transaction Isolation Levels.
🔹 Các Mức Cách Ly trong Transaction
READ UNCOMMITTED
✅ Có
✅ Có
✅ Có
READ COMMITTED
❌ Không
✅ Có
✅ Có
REPEATABLE READ
❌ Không
❌ Không
✅ Có
SERIALIZABLE
❌ Không
❌ Không
❌ Không
🔹 Vấn Đề Cần Giải Quyết
Dirty Read 🟠
Một transaction có thể đọc dữ liệu chưa commit từ transaction khác.
Có thể dẫn đến trạng thái không nhất quán khi transaction bị rollback.
Giải pháp: READ COMMITTED trở lên.
Non-repeatable Read 🟡
Một transaction đọc cùng một bản ghi nhiều lần nhưng nhận được các giá trị khác nhau do transaction khác đã thay đổi dữ liệu.
Giải pháp: REPEATABLE READ trở lên.
Phantom Read 🔴
Một transaction thực hiện cùng một truy vấn nhiều lần nhưng nhận được tập kết quả khác nhau do transaction khác đã thêm/xóa dữ liệu.
Giải pháp: SERIALIZABLE.
🔹 Cấu hình Isolation Level trong Spring Boot
Spring Data JPA hỗ trợ việc thiết lập mức cách ly bằng @Transactional(isolation = Isolation.LEVEL)
.
Ví dụ: Chỉ đọc dữ liệu đã được commit (READ COMMITTED):
2. Pessimistic vs Optimistic Locking
Locking giúp tránh xung đột dữ liệu trong các ứng dụng nhiều luồng.
🔹 Optimistic Locking (Khóa Lạc Quan)
Sử dụng
@Version
để kiểm soát xung đột mà không cần khóa cấp database.Nếu dữ liệu bị sửa đổi bởi transaction khác, JPA sẽ ném ngoại lệ (
OptimisticLockException
).Ưu điểm: Không khóa dữ liệu, hiệu suất tốt hơn.
Nhược điểm: Nếu có nhiều cập nhật đồng thời, có thể gây lỗi lặp.
🔹 Cách triển khai Optimistic Locking với @Version
Khi một bản ghi được đọc,
version
sẽ được lưu lại.Khi cập nhật bản ghi, JPA kiểm tra xem
version
có thay đổi không.Nếu có thay đổi từ transaction khác, JPA sẽ ném ngoại lệ.
🔹 Cách xử lý ngoại lệ Optimistic Locking
🔹 Pessimistic Locking (Khóa Bi Quan)
Dùng khi dữ liệu được đọc và ghi thường xuyên.
Có 2 loại khóa chính:
PESSIMISTIC_READ
: Chặn ghi nhưng vẫn cho phép đọc.PESSIMISTIC_WRITE
: Chặn cả đọc và ghi từ các transaction khác.
🔹 Cách dùng Pessimistic Locking trong Spring Data JPA
Khi một transaction lấy dữ liệu, nó sẽ chặn các transaction khác đọc và ghi vào bản ghi đó.
🔹 Khi nào nên dùng? ✅ Optimistic Locking → Khi xung đột hiếm xảy ra. ✅ Pessimistic Locking → Khi có nhiều cập nhật đồng thời vào cùng dữ liệu.
3. Deadlock & Database Locking Strategies
🔹 Deadlock là gì?
Deadlock xảy ra khi hai transaction chờ nhau để giải phóng khóa và không thể tiếp tục.
VD:
Transaction A khóa Bản ghi 1, cần Bản ghi 2.
Transaction B khóa Bản ghi 2, cần Bản ghi 1.
Cả hai bị kẹt 🛑.
🔹 Cách tránh Deadlock
Duy trì thứ tự truy cập dữ liệu
Luôn truy vấn dữ liệu theo cùng một thứ tự để tránh deadlock.
Giới hạn thời gian khóa
Dùng
lock timeout
để tránh chờ vô hạn:
@Transactional(timeout = 5)
Sử dụng Retry MechanismKhi bị deadlock, thử lại giao dịch sau vài mili giây.
Advisory Locks trong PostgreSQL
Advisory Lock là một dạng khóa mà ứng dụng tự quản lý thay vì database tự động khóa bản ghi.
Dùng khi cần kiểm soát truy cập mà không cần khóa row-level.
Sử dụng cho các tác vụ mà không muốn JPA tự động khóa dữ liệu.
🚀 Tổng Kết
READ COMMITTED
Ngăn dirty read nhưng cho phép non-repeatable read
REPEATABLE READ
Ngăn dirty read và non-repeatable read nhưng có phantom read
SERIALIZABLE
Chặn mọi xung đột nhưng có thể gây chậm
Optimistic Locking (@Version
)
Khi xung đột hiếm, ít ảnh hưởng hiệu suất
Pessimistic Locking (@Lock
)
Khi có nhiều transaction ghi đồng thời
Advisory Locks
Khi muốn kiểm soát thủ công mà không khóa database
Last updated