Hai chiến lược giải quyết xung đột khi nhiều transaction cùng sửa một row.
Pessimistic Locking — "Chắc chắn sẽ có xung đột, khóa ngay khi đọc":
// SELECT ... FOR UPDATE — giữ khóa đến khi commit
Product p = entityManager.find(Product.class, id, LockModeType.PESSIMISTIC_WRITE);
p.setStock(p.getStock() - qty);- DB khóa row → các transaction khác phải chờ.
- An toàn nhưng giảm throughput, có thể deadlock.
Optimistic Locking — "Xung đột hiếm, kiểm tra khi commit":
@Entity
class Product {
@Version
private Long version; // Spring tự quản lý
}
// Khi UPDATE, Spring thêm: WHERE id=? AND version=?
// Nếu version đã đổi (người khác update trước) → OptimisticLockException| Pessimistic | Optimistic | |
|---|---|---|
| Khóa DB | ✅ Ngay khi đọc | ❌ Không khóa |
| Xung đột | Ngăn trước | Phát hiện khi commit |
| Hiệu năng | Thấp (chờ khóa) | Cao (không block) |
| Dùng khi | Xung đột thường xuyên, financial | Xung đột hiếm, inventory |
Xử lý OptimisticLockException:
try {
service.decreaseStock(productId, qty);
} catch (OptimisticLockException e) {
// Retry hoặc thông báo "dữ liệu đã thay đổi, thử lại"
}2026 best practice: Optimistic locking cho hầu hết CRUD.
Pessimistic cho critical section (account balance deduction).
Two strategies for resolving conflicts when multiple transactions modify the same row.
Pessimistic Locking — "Conflicts will happen; lock immediately on read":
// SELECT ... FOR UPDATE — holds lock until commit
Product p = entityManager.find(Product.class, id, LockModeType.PESSIMISTIC_WRITE);
p.setStock(p.getStock() - qty);- DB locks the row → other transactions must wait.
- Safe but reduces throughput; can cause deadlocks.
Optimistic Locking — "Conflicts are rare; check at commit time":
@Entity
class Product {
@Version
private Long version; // Spring manages automatically
}
// On UPDATE, Spring adds: WHERE id=? AND version=?
// If version has changed (someone else updated first) → OptimisticLockException| Pessimistic | Optimistic | |
|---|---|---|
| DB lock | ✅ On read | ❌ None |
| Conflict | Prevented | Detected at commit |
| Performance | Lower (waiting) | Higher (no blocking) |
| Use when | Frequent conflicts, financial | Rare conflicts, inventory |
Handling OptimisticLockException:
try {
service.decreaseStock(productId, qty);
} catch (OptimisticLockException e) {
// Retry or inform user "data changed, please try again"
}2026 best practice: Optimistic locking for most CRUD operations.
Pessimistic for critical sections (account balance deductions).