1. 程式人生 > >mysql innodb引擎下的行鎖由於意外沒有被釋放,導致後面的請求無法繼續,怎麼辦?

mysql innodb引擎下的行鎖由於意外沒有被釋放,導致後面的請求無法繼續,怎麼辦?

在一個@Transactional註解的方法中進行除錯,但莫名其妙的就報了下面這個錯誤:

這裡寫圖片描述

從內容上看不出個所以然,大概的猜測是事務開啟了,一直沒有commit,導致MySQL的行被鎖住了。下面這個錯誤證實了我的想法,再次更新同一條資料時,依然失敗。

這裡寫圖片描述

那麼,該怎麼解決掉這個問題呢?

網上找資料唄。

有幾篇文章值得深入的學習和思考:

  1. mysql的鎖–行鎖,表鎖,樂觀鎖,悲觀鎖,https://www.cnblogs.com/deliver/p/5730616.html
  2. DRUID連線池的實用 配置詳解,https://www.cnblogs.com/wuyun-blog/p/5679073.html
  3. mysql innodb引擎下的行鎖獲得後 由於意外沒有被釋放,導致後面的請求無法獲得該行鎖,怎麼辦?(由於CSDN的Markdown有些小問題,為了顯示得更舒服一點,網址在第四點)
  4. https://www.zhihu.com/question/56380924/answer/149316845

首先,我的資料庫連結使用的是阿里的Druid,所以第二篇文章中讀到以下關鍵資訊:

testOnBorrow |true| 申請連線時執行validationQuery檢測連線是否有效,做了這個配置會降低效能。

而我專案中的該值設定為false。瞬間感覺問題就要馬上解決了,但不瞭解事情的真相就想要解決問題,是不可能的。果然,把資料庫連結配置中testOnBorrow 設定為true,於事無補。

那麼,第三篇文章對我應該是有幫助的。畢竟我先要把鎖釋放掉,因為我還有一大頓的測試要做。從第三篇文章中我找到以下關鍵資訊:

其次,如果真的出現了這樣的問題,那就通過命令show engine innodb status\G,找到ACTIVE時間長的(需要通過其中資訊確定一下是不是這個事務,最好別找錯了),通過這些資訊找到對應的thread id,然後kill connection threadid,將其殺掉,恢復業務正常執行,然後再去改業務程式碼上存在的問題吧。

這位朋友提供的方法我認為是正解,於是使用Navicat進入資料庫的命令列介面,執行:
show engine innodb status\G


結果令人失望:

mysql> show engine innodb status\G;
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘\G’ at line 1
mysql>

該怎麼辦呢?

網上找資料唄。

有朋友提供這樣的資訊,說這條語句只能在mysql的cmd或者shell介面下執行,我很懷疑這句話的正確性。但事實證明我是多麼的無知,他說的是對的,我的懷疑是多餘的。

這裡寫圖片描述

為什麼?為什麼真理永遠被別人掌握?為什麼我就偏偏不知道呢?

對於技術能力在我之上的,能解決我問題的人,我感到由衷的佩服,請收下我的膝蓋。

嗯,不過,等一等,這條語句show engine innodb status\G;執行後的結果都什麼玩意啊?我表示看不懂,難道不看了嗎?

當然不行,要解決問題啊,耐著頭皮繼續看唄。

這裡寫圖片描述

嗯,發現了“金銀島”,這不就是“ACTIVE時間長的”?懂行的人的話語永遠都那麼少,那麼精闢,那麼直達人心。其中thread id為“221489”,還等什麼,立馬kill掉它。

mysql> kill connection  221489;
Query OK, 0 rows affected (0.00 sec)

mysql>

我就好像是出門大張的小兵,出門之前元帥告訴我要這麼這麼這麼這麼做,嗯,我點點頭,表示對他的話一知半解。到底對不對?有待檢驗。

[SQL]UPDATE mem_point SET `shop_offset` = 0 WHERE uid=35;
受影響的行: 1
時間: 0.000s

嗯,沒錯,老闆說得千真萬確,之前一直被鎖的update,現在可以順利執行了。
果然,有的時候,你要相信,當自己無知的時候,別人說的話永遠都是真理。你需要做的就是,去檢驗它是否真的是真理。


我就是這一個人,永遠都在進步。