在一個@Transactional注解的方法中進行調試,但莫名其妙的就報了下面這個錯誤:
從内容上看不出個是以然,大概的猜測是事務開啟了,一直沒有commit,導緻MySQL的行被鎖住了。下面這個錯誤證明了我的想法,再次更新同一條資料時,依然失敗。
那麼,該怎麼解決掉這個問題呢?
網上找資料呗。
有幾篇文章值得深入的學習和思考:
mysql的鎖–行鎖,表鎖,樂觀鎖,悲觀鎖,
https://www.cnblogs.com/deliver/p/5730616.htmlDRUID連接配接池的實用 配置詳解,
https://www.cnblogs.com/wuyun-blog/p/5679073.htmlmysql innodb引擎下的行鎖獲得後 由于意外沒有被釋放,導緻後面的請求無法獲得該行鎖,怎麼辦?(由于CSDN的Markdown有些小問題,為了顯示得更舒服一點,網址在第四點)
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)
我就好像是出門大張的小兵,出門之前元帥告訴我要這麼這麼這麼這麼做,嗯,我點點頭,表示對他的話一知半解。到底對不對?有待檢驗。
[SQL]UPDATE mem_point SET `shop_offset` = 0 WHERE uid=35;
受影響的行: 1
時間: 0.000s
嗯,沒錯,老闆說得千真萬确,之前一直被鎖的update,現在可以順利執行了。
果然,有的時候,你要相信,當自己無知的時候,别人說的話永遠都是真理。你需要做的就是,去檢驗它是否真的是真理。