模型定義事務如何被管理(誰管理、語法規則);策略解決具體場景用什麼模型、屬性怎麼配、如何優化。混淆兩者是常見錯誤。
| 模型 | 管理者 | 開發者職責 | 典型技術 |
|---|---|---|---|
| 本地事務 | 資源本身(DB) | 管理連接、手動 commit/rollback | JDBC Connection.setAutoCommit(false) |
| 編程式事務 | 事務管理器 | 獲取事務、編寫 begin/commit/rollback 代碼 | JTA UserTransaction、Spring TransactionTemplate |
| 聲明式事務 | 容器/框架 | 定義事務屬性(傳播、隔離、超時、只讀) | EJB CMT、Spring @Transactional |
場景:客戶端發起多個服務調用完成一個業務單元(如下單:扣庫存、建訂單、扣款)。
特點:事務邊界在客戶端,需分佈式事務協調(2PC/補償/TCC)。
技術:Seata AT/XT 模式、Spring Cloud 分佈式事務、Saga 模式編排器。
場景:服務入口為粗粒度 API(Service Facade),內部多個 DAO/Repository 操作需在同一事務中。
特點:最常見,聲明式事務在 Service 方法上生效。
配置:@Transactional(rollbackFor = Exception.class),傳播行為 REQUIRED(默認)。
場景:高吞吐、低延遲系統,長事務導致鎖競爭、連接池耗盡。
核心原則:縮小事務範圍、縮短事務持有時間。
readOnly=true(優化器可跳過鎖、快照讀)。場景:極致性能要求(如交易撮合、實時計費),需在保證原子性前提下最大化吞吐。
極端手段:
// Spring 聲明式事務(最主流)
@Service
@Transactional(rollbackFor = Exception.class, timeout = 30)
public class OrderService {
@Autowired OrderMapper orderMapper;
@Autowired InventoryMapper inventoryMapper;
public void createOrder(OrderDTO dto) {
inventoryMapper.deductStock(dto.getSkuId(), dto.getQty()); // 扣庫存
orderMapper.insert(dto.toOrder()); // 建訂單
// 異常自動回滾
}
}
// EJB 3.0 容器管理事務(CMT)
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class OrderBean implements OrderRemote {
@PersistenceContext EntityManager em;
@EJB InventoryBean inventoryBean;
public void createOrder(OrderDTO dto) {
inventoryBean.deductStock(dto.getSkuId(), dto.getQty());
em.persist(dto.toOrder());
}
}
| 屬性 | 含義 | 適用場景 |
|---|---|---|
| REQUIRED | 有事務加入,無則新建 | 90% 業務方法,默認選擇 |
| REQUIRES_NEW | 掛起當前,強制新建 | 獨立審計日誌、通知發送、補償操作 |
| MANDATORY | 必須在事務中,否則拋異常 | 核心寫操作,強制調用方開啟事務 |
| SUPPORTS | 有則加入,無則非事務運行 | 純查詢方法,配合 readOnly=true |
| NOT_SUPPORTED/NEVER | 以非事務方式運行 | 長耗時查詢、外部 API 調用、報表導出 |
| NESTED | 嵌套事務(僅 Spring/JDBC 支持) | 部分回滾場景,如批量導入單行失敗回滾該行 |
rollbackFor。事務模型提供基礎設施,事務策略決定系統穩定性與性能上限。從 API 層策略起步,隨業務演進引入高併發/高速策略,分佈式場景謹慎選擇客戶端編排。深諳傳播行為、隔離級別、鎖機制,才能駕馭複雜事務場景。