天天看點

Mybatis-update - 資料庫死鎖 - 擷取資料庫連接配接池等待1.mysql資料庫死鎖2.Mybatis中datasource的資料庫連接配接數

最近學習測試mybatis,單個增删改查都沒問題,最後使用mvn test的時候發現了幾個問題:

update失敗,原因是資料庫死鎖

select等待,原因是connection連接配接池被用光了,需要等待

get:

要勇于探索,堅持就是勝利。剛看到錯誤的時候直接懵逼,因為錯誤完全看不出來,屬于架構内部報錯,在猶豫是不是直接睡覺得了,畢竟也快12點了。最後還是給我一點點找到問題所在了。

同上,要敢于去深入你不了解的代碼,敢于研究不懂的代碼。

距離一個合格的碼農越來越遠了,因為越學越覺得漏洞百出,自己的代碼到處都是坑。是以,一定要記錄下來。

下面記錄這兩個問題。

這裡,感謝http://www.cnblogs.com/lin-xuan/p/5280614.html,我找到了答案。在這裡,我還是重制一下:

資料庫死鎖是事務性資料庫 (如SQL Server, MySql等)經常遇到的問題。除非資料庫死鎖問題頻繁出現導緻使用者無法操作,一般情況下資料庫死鎖問題不嚴重。在應用程式中進行try-catch就可以。那麼資料死鎖是如何産生的呢? InnoDB實作的是行鎖 (row level lock),分為共享鎖 (S) 和 互斥鎖 (X)。 共享鎖用于事務read一行。 互斥鎖用于事務update或delete一行。 當客戶A持有共享鎖S,并請求互斥鎖X;同時客戶B持有互斥鎖X,并請求共享鎖S。以上情況,會發生資料庫死鎖。

如果還不夠清楚,請看下面的例子。

雙開兩個mysql用戶端

用戶端A:

開啟事務,并鎖定共享鎖S 在id=12的時候:

用戶端B:

開啟事務,嘗試删除id=12:

删除操作需要互斥鎖 (X),但是互斥鎖X和共享鎖S是不能相容的。是以删除事務被放到鎖請求隊列中,客戶B阻塞。

這時候用戶端A也想要删除12:

和參考文章不同的是,居然删除成功了,但用戶端B出錯了:

于是,我嘗試删除13,這下都阻塞了:

Mybatis-update - 資料庫死鎖 - 擷取資料庫連接配接池等待1.mysql資料庫死鎖2.Mybatis中datasource的資料庫連接配接數

我的mybatis測試代碼中,因為上一個測試沒有commit導緻死鎖,commit後就ok了。在這裡,我想說,資料庫的東西全還給老師了,關于鎖以及事務需要重新溫習一下了。

當我mvn test的時候,我發現有個查詢的test列印日志:

于是,果然等了一段時間後才執行成功。跟蹤源碼,找到這處日志就明白了。首先,我這裡使用的資料庫連接配接配置是mybatis預設的:

當資料庫連接配接池的連接配接數用光了之後就要等20s再去擷取:

Mybatis-update - 資料庫死鎖 - 擷取資料庫連接配接池等待1.mysql資料庫死鎖2.Mybatis中datasource的資料庫連接配接數
Mybatis-update - 資料庫死鎖 - 擷取資料庫連接配接池等待1.mysql資料庫死鎖2.Mybatis中datasource的資料庫連接配接數

View Code

當連接配接數少于10個的時候回建立,超過10個就會等待,不然就報錯。

唯有不斷學習方能改變!

-- <b>Ryan Miao</b>