記一次排查mysql數據庫連接未關閉問題的過程


在一些項目中由於一些特殊原因仍然保留着顯示的獲取數據庫連接(Connection)、提交事務、回滾事務、關閉連接等操作;其中關閉連接是比較容易疏忽又比較難在前期發現的問題。

我是如何排查連接未關閉的問題的? 首先還是提出3W:

1.What?

  數據庫連接是應用服務器和數據庫之間建立的tcp連接,在獲取連接並進行操作后需要手動關閉以釋放資源,就像是文件流一樣,資源是有限的。

2.Why?

  連接不釋放會導致連接池無法回收連接,進而數據庫連接逐漸被占滿,直到超出數據庫設置的最大連接數而拒絕服務,顯而易見這是不能接受的;同時由於數據庫連接也是tcp連接,未釋放的連接會占用應用服務器和數據庫服務器之間的tcp連接,有些情況下會導致無法應對突發流量(已經沒有足夠多的tcp連接)。

3.How?

  顯示的調用connection.close()關閉連接或者利用spring管理連接。

我的排查步驟

1.掃描代碼

  由於是顯示的開啟連接和關閉連接,則可以通過掃描代碼文件,獲取每個java文件中開啟連接的次數和關閉連接的次數,如果關閉連接的次數<開啟連接的次數,則說明很可能這里的代碼未關閉連接,則可以進一步排查。

  但是由於每個開發人員的代碼風格不一致,比如有些是connection有些是conn;有些在外部開啟了連接,在if-else內部各關閉了2次連接等情況,所以掃描代碼的方式可能不太准確。

2.數據庫層面排查

  如果未關閉連接,則其事務就不會被提交;通過mysql提供的事務表和開啟performance_schema后的線程表即可定位未提交事務執行的sql,根據sql反向查找代碼,以定位問題所在。

  下面通過一個測試程序來模擬

  

 

 

   執行代碼,執行后,主線程等待

  

 

  查看mysql事務表,得到thread_id(其實是processlist_id,見下圖)

  

 

  根據processlist_id查詢performance_schema線程信息

  

 

 

 

   根據thread_id查詢具體的sql

  

 

  然后就是根據sql反向查找代碼了...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM