事務是企業級應用數據一致性的基石。Java 體系中存在三類事務:JDBC 事務(本地)、JTA 事務(分布式標準)、容器事務(Spring/EJB 封裝)。本文聚焦前兩者,通過代碼對比、架構圖解、優缺點深度剖析,揭示為何 JDBC 事務無法支撐分布式場景,以及 JTA 如何通過 XA 規范實現跨資源管理器的原子提交。
public void jdbcTransfer() {
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, pwd);
conn.setAutoCommit(false); // 關鍵:開啟手動事務模式
Statement stmt = conn.createStatement();
stmt.execute("UPDATE t_account SET amount = amount - 500 WHERE account_id = 'A'");
stmt.execute("UPDATE t_account SET amount = amount + 500 WHERE account_id = 'B'");
conn.commit(); // 兩步操作原子提交
} catch (SQLException e) {
if (conn != null) conn.rollback(); // 異常全量回滾
e.printStackTrace();
} finally {
// 關閉資源
}
}
| 特性 | 說明 |
|---|---|
| 綁定維度 | 單個 Connection 對象 |
| 適用範圍 | 單一數據庫、單一數據源 |
| API 複雜度 | 低(setAutoCommit/commit/rollback) |
| 性能 | 高(無協調器開銷) |
| 分布式支持 | ❌ 完全不支持 |
若轉賬涉及 BankA 和 BankB 兩個不同數據庫,需要兩個 Connection,JDBC 事務無法保證它們「要麼全成功、要麼全失敗」。這正是分布式事務誕生的動力。
現代電商架構:訂單服務、賬戶服務、積分服務、會計服務、通知服務分別部署在不同機器、操作不同數據庫。一個下單請求觸發 5 個 RPC 調用,任一失敗需全鏈路回滾。JDBC 事務無能為力,JTA 應運而生。
XAResource 接口。XADataSource、XAConnection、XAResource),實現兩階段提交(2PC)。public void jtaTransfer() {
UserTransaction tx = null;
Connection conn = null;
try {
// 1. 從 JNDI 獲取事務管理器與 XADataSource
Context ctx = new InitialContext();
tx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
DataSource ds = (DataSource) ctx.lookup("java:/XAOracleDS"); // 必須是 XADataSource
tx.begin(); // 開啟全局事務
conn = ds.getConnection();
conn.setAutoCommit(false); // XA 連接不支持自動提交
Statement stmt = conn.createStatement();
stmt.execute("UPDATE t_account SET amount = amount - 500 WHERE account_id = 'A'");
stmt.execute("UPDATE t_account SET amount = amount + 500 WHERE account_id = 'B'");
tx.commit(); // 統一提交
} catch (Exception e) {
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
// 關閉資源
}
}
| 方法 | 作用 |
|---|---|
begin() | 開啟新事務,綁定到當前線程 |
commit() | 提交事務(觸發 2PC 準備/提交階段) |
rollback() | 回滾事務 |
setRollbackOnly() | 標記事務僅能回滾 |
setTransactionTimeout(seconds) | 設置超時時間,超時自動回滾 |
| 模式 | 典型產品 | 適用場景 |
|---|---|---|
| J2EE 容器內置 | JBoss/WildFly (Narayana), WebLogic, WebSphere | 全棧 Java EE 應用服務器 |
| 獨立 JTA 管理器 | Atomikos, Bitronix, Narayana (Standalone) | Tomcat, Jetty, Spring Boot, 單元測試 |
Spring Boot 集成 Atomikos 示例:
@Bean
public UserTransactionManager transactionManager() {
UserTransactionManager tm = new UserTransactionManager();
tm.setForceShutdown(true);
return tm;
}
@Bean
public UserTransaction userTransaction() throws SystemException {
UserTransactionImp ut = new UserTransactionImp();
ut.setTransactionTimeout(300);
return ut;
}
@Bean
public JtaTransactionManager springTransactionManager() throws SystemException {
return new JtaTransactionManager(transactionManager(), userTransaction());
}
| 維度 | 優點 | 缺點 |
|---|---|---|
| 事務範圍 | 跨多個數據庫、JMS、EJB 等異構資源 | 需所有資源實現 XA 接口(非標準資源難接入) |
| 一致性 | 嚴格 ACID(2PC 保證) | 同步阻塞、協調器單點、性能開銷大 |
| 開發複雜度 | 標準化 API | JNDI 查找、XADataSource 配置、異常處理極其繁瑣 |
| 部署限制 | 容器管理 | 強依賴應用服務器,代碼可移植性差 |
由於 JTA/2PC 的同步阻塞、長事務鎖資源、協調器單點等缺陷,業界已轉向柔性事務方案:
Spring Cloud Alibaba Seata (AT 模式) 則在應用層模擬 2PC,無需數據庫 XA 支持,兼顧易用性與一致性。
@Transactional (Spring 管理 JDBC/JPA 事務);微服務架構選型 Seata AT/TCC、RocketMQ 事務消息等柔性事務框架,根據業務一致性要求與性能指標權衡。