WebLogic 執行 XA 事務時遇到 XAER_NOTA: The XID is not valid,意味著資源管理器 (RM: DB/MQ) 端找不到對應的事務分支。本文深度剖析兩大根因:**分支被 RM 超時清理**與**多 XA DataSource 指向同一連接池導致 XAResource 身份混淆**,並給出配置級與代碼級解決方案。
XAER_NOTA = 事務分支在 RM 端不存在。兩種可能:1) 分支被超時清理;2) 分支壓根未在 RM 端發起。
xaStart() 時可通知 RM 分支超時時間。xaStart/xaEnd 拋 XAER_NOTA。xaStart() 時傳遞超時時間給 RM,RM 據此延長分支保留期限。XADatasource_11 → XAPool_A → Database_A
XADatasource_21 → XAPool_B → Database_B
// 業務需求新增別名數據源,錯誤指向同池
XADatasource_12 → XAPool_A (同池!)
XADatasource_22 → XAPool_B (同池!)
registerResource(poolName, XAResource, props) 註冊到 **Process-wide resourceDescriptorList**。unregisterResource(poolName) 移除舊同名資源。XADatasource_12 導致 XADatasource_11 在 resourceDescriptorList 中被移除!同理 22 移除 21。// 1. 獲取連接 → enlistResource(XAResource)
ServerTransactionImpl.enlistResource(xar)
// 2. 檢查 resourceDescriptorList 中是否有 XADatasource_11 對應的描述符
// → 不在 (已被 12 移除)
// 3. 檢查 transaction-wide resourceInfoList
// → 空 (新事務)
// 4. 創建 XAServerResourceInfo(xar)
// → 再次查 resourceDescriptorList,按實例不存在,按類名 "weblogic.jdbc.jta.DataSource" 找到 XADatasource_12 的描述符
// → 復用該描述符,resourceInfo.name = "weblogic.jdbc.jta.DataSource"
// 5. resourceInfoList 中無同名 → enlistElseWhere = false → 傳 TMNOFLAGS (新分支)
// → xaStart(xid, TMNOFLAGS) → Database_A 創建新分支 ✓
// 6. 後續獲取 XADatasource_21 連接
// → 同邏輯,resourceInfo.name 同為 "weblogic.jdbc.jta.DataSource"
// → 發現 resourceInfoList 中已有同名 → enlistElseWhere = true
// → 傳 TMJOIN (加入現有分支) → xaStart(xid, TMJOIN) 發送給 Database_B
// → Database_B 無此全局事務對應分支 → **XAER_NOTA 爆發!**
11/21) 對應兩個不同數據庫 (A/B),應創建**兩個獨立分支** (TMNOFLAGS 兩次)。weblogic.jdbc.jta.DataSource 作為 resourceInfo.name,第二個被誤判為「已在別處 enlist」,強行 TMJOIN 導致跨庫分支錯位。WebLogic 限制:**同一進程中,多個 XA DataSource 不得指向同一連接池**,也不得多個連接池指向同一數據庫 (若共用 XAResource 實現類)。違反此限制屬於配置錯誤,非產品 Bug。WebLogic 8.1 SP6 已輸出明確錯誤提示。
| 場景 | 正確做法 |
|---|---|
| 需要多個邏輯數據源訪問同一物理庫 | 使用 **Multi Data Source** (負載均衡/故障轉移) 或單一 DataSource 供多模塊共用,**嚴禁創建多個 XA DataSource 指向同一 Pool** |
| 需要隔離事務邊界 | 不同事務域使用**不同連接池 + 不同物理數據庫實例/Schema** |
| 長事務超時風險 | 啟用 Enable XA Transaction Timeout,設置合理值 (> 全局事務超時) |
| 監控與告警 | 監控 XAER_NOTA 異常計數、事務超時率、連接池 NumUnavailable |
XAER_NOTA 要么是**時間維度**上的超時清理 (配置 XA Transaction Timeout 解決),要么是**身份維度**上的資源混淆 (避免多 XA DataSource 共用 Pool/DB)。前者是參數調優,後者是架構原則 —— **一個 XA 連接池只對應一個邏輯 XA DataSource,一個物理數據庫實例建議只對應一個 XA 連接池**。