天天看點

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

版權聲明:歡迎轉載,請注明沉默王二原創。 https://blog.csdn.net/qing_gee/article/details/80108576

在一個@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,現在可以順利執行了。

果然,有的時候,你要相信,當自己無知的時候,别人說的話永遠都是真理。你需要做的就是,去檢驗它是否真的是真理。

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