首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis 死鎖與連接池等待問題排查實戰

     編輯:Java 相關知識

MyBatis 更新死鎖與連接池耗盡問題深度排查

問題現象

  • 單元測試通過,但 mvn test 運行多個測試時出現:
  • 更新失敗:資料庫死鎖
  • 查詢卡住:等待連接池可用連接

問題一:MySQL 死鎖分析與解決

死鎖原理

InnoDB 行級鎖:共享鎖(S,SELECT ... LOCK IN SHARE MODE)與排他鎖(X,UPDATE/DELETE)。

死鎖場景:

  1. 事務 A 持有 S 鎖(查詢),請求 X 鎖(更新)
  2. 事務 B 持有 X 鎖(更新),請求 S 鎖(查詢)
  3. 雙方互相等待,形成環路

實測復現

-- 客戶端 A
START TRANSACTION;
SELECT * FROM blog WHERE id = 12 LOCK IN SHARE MODE; -- 持有 S 鎖

-- 客戶端 B
START TRANSACTION;
DELETE FROM blog WHERE id = 12; -- 需要 X 鎖,阻塞等待

-- 客戶端 A 繼續
DELETE FROM blog WHERE id = 12; -- 請求 X 鎖,觸發死鎖檢測
-- 客戶端 B 報錯:ERROR 1213 (40001): Deadlock found

測試代碼根因

單元測試中,前一個測試開啟事務未提交(@Transactional 未回滾或手動管理事務未 commit),導致鎖持有不釋放,後續測試觸發死鎖。

解決方案

  • 測試方法加 @Transactional 並設置 rollback = true(預設)
  • 手動管理事務務必 commit() 或 rollback()
  • 檢查業務代碼:避免長事務、統一加鎖順序、適當降低隔離級別

問題二:連接池耗盡等待

現象日誌

DEBUG [PooledDataSource] - Waiting as long as 20000 milliseconds for connection.

源碼分析

MyBatis 預設 POOLED 數據源配置:

<dataSource type="POOLED">
    <property name="driver" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</dataSource>

PooledDataSource 核心邏輯:

  • 最大活躍連接數 poolMaximumActiveConnections = 10(預設)
  • 超過 10 個併發請求時進入等待,最長等待 poolTimeToWait = 20000ms
  • 等待超時拋出異常

根因

測試用例未正確關閉 SqlSession,導致連接未歸還池中。併發測試時迅速耗盡 10 個連接。

解決方案

  1. 確保 SqlSession 關閉:使用 try-with-resources 或 finally 塊
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
    // 執行操作
} // 自動關閉,歸還連接
  1. 調整連接池參數:根據併發需求增大
<dataSource type="POOLED">
    <property name="poolMaximumActiveConnections" value="50"/>
    <property name="poolMaximumIdleConnections" value="20"/>
    <property name="poolTimeToWait" value="10000"/>
</dataSource>
  1. 生產環境建議:使用成熟連接池(HikariCP、Druid)替換 MyBatis 內建池

總結經驗

  • 死鎖多因事務管理不當,測試環境尤甚
  • 連接洩漏是連接池耗盡主因,SqlSession 必須成對開閉
  • 善用工具:SHOW ENGINE INNODB STATUS 分析死鎖,VisualVM 監控連接池狀態
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved