Transaction abstraction và declarative boundary
Spring transaction là interceptor quanh một use case, phối hợp transaction manager với resource thật. Muốn dự đoán commit hay rollback, cần phân biệt proxy boundary, logical scope và physical transaction.
Kiến trúc
PlatformTransactionManager điều phối resource-specific transaction; TransactionDefinition chứa propagation, isolation, timeout và read-only; TransactionStatus theo dõi state. Declarative transaction dùng advisor/proxy quanh method. Resource binding thường gắn với execution thread, vì vậy nhảy thread làm mất context nếu không dùng model tương ứng.
Logical và physical transaction
| Propagation | Physical behavior | Rủi ro chính |
|---|---|---|
REQUIRED | Tham gia transaction hiện có hoặc tạo mới. | Mỗi method là logical scope; inner rollback-only có thể làm outer commit ném UnexpectedRollbackException. |
REQUIRES_NEW | Suspend outer và tạo physical transaction độc lập. | Cần connection khác; dùng lồng nhau nhiều có thể làm cạn pool. |
NESTED | Dùng savepoint trong physical transaction nếu resource hỗ trợ. | Không đồng nghĩa transaction độc lập; support phụ thuộc manager/database. |
SUPPORTS/NOT_SUPPORTED | Tham gia nếu có hoặc chạy ngoài transaction. | Caller context làm behavior thay đổi; cần dùng có chủ đích. |
Isolation, timeout và read-only
Isolation annotation yêu cầu database level nhưng behavior thực phụ thuộc engine và configuration. readOnly là hint hoặc optimization, không phải authorization hay security guarantee. Transaction timeout cần phù hợp query/lock timeout và ngắn hơn request deadline để tránh giữ resource sau khi caller đã bỏ cuộc.
Rollback rules
Mặc định RuntimeException và Error gây rollback; checked exception thường commit nếu không có rule khác. Đừng catch exception trong transactional method rồi nuốt khiến proxy tưởng method thành công. Preserve cause và map exception ở boundary sau khi transaction semantics đã rõ.
Class-level @Transactional là default cho eligible methods của class, nhưng không nên suy luận rằng annotation luôn kế thừa qua mọi interface/class arrangement. Khi có nhiều transaction managers, chọn manager bằng qualifier hoặc cấu hình rõ; để annotation không định danh manager có thể chọn sai resource hoặc trở nên ambiguous.
Transaction synchronization
Callback beforeCommit, afterCommit và afterCompletion phù hợp resource coordination nhẹ. Tuy nhiên gửi message trong afterCommit vẫn có thể fail sau DB commit; transactional outbox cung cấp durable handoff tốt hơn khi cần bảo đảm eventual publish.
Boundary thực tế
- Đặt transaction ở application use case, bao trùm invariant database.
- Không giữ transaction qua remote call chậm nếu không có lý do mạnh.
- Optimistic hoặc pessimistic lock chỉ có ý nghĩa trong transaction thật.
@Asynckhông tự tiếp tục transaction của caller.- Reactive transaction dùng Reactor context thay vì ThreadLocal.
- Self-invocation bỏ qua transactional proxy giống các Spring AOP advice khác.
REQUIRES_NEW có thể chờ connection mới vô hạn. Tăng pool chỉ trì hoãn sự cố nếu call graph vẫn giữ nhiều transaction lồng nhau.