支付業務出現詭異現象:事務失敗調用 ROLLBACK,只有最後一條 SQL 回滾,前面的寫操作全部生效。排查發現:網絡抖動導致首次建立連接時發送的 BEGIN 丟包,驅動自動重連後會話變為 autocommit=ON,後續所有語句隱式提交,ROLLBACK 自然無法回滾已提交的語句。
BEGIN → 網絡丟包,MySQL 未收到。autoReconnect=true)。autocommit=1,應用不知情繼續執行 DML。ROLLBACK,僅回滾最後一條隱式事務。在 BEGIN 時將應用伺服器時間戳寫入一張專用表(或用戶變數),後續每條 SQL 執行前讀取比對;時間戳不一致則判定連接已重置,拋棄重試。缺點:每條 SQL 額外一次網絡往返,效能大幅下降。
| 方案 | 原理 | 適用場景 |
|---|---|---|
| 關閉自動重連 | JDBC autoReconnect=false、HikariCP autoCommit=false,拋出異常由上層統一重試 |
所有生產環境,強制業務感知連接失敗 |
| 使用 XA 事務 / 分佈式事務管理器 | 全局事務 ID 確保原子性,跨節點亦可回滾 | 微服務、跨庫事務 |
| 應用層冪等 + 重試 | 業務邏輯冪等設計,連接斷開直接重試整個事務邏輯 | 高可用架構,配合重試框架(如 Resilience4j) |
| 驅動層連接驗證 | connection.isValid(1) 或 SELECT 1 校驗連接存活,失效則重建並重新 BEGIN |
舊系統無法改造自動重連行為時 |
永遠不要依賴驅動自動重連維持事務上下文。 事務邊界必須由應用顯式控制,連接異常即拋棄整個事務上下文重試。