問題實戰 Lock wait timeout exceeded try restarting transaction

背景:

項目對轉賬的功能進行優化,測試的時候,發現原轉賬功能無法使用。

mysql報錯:

Statement cancelled due to timeout or client request

問題分析:

從字面意思來看是,預編譯在等待執行或執行的時候,因爲超時而取消了。

那麼什麼原因呢?

1.語句執行過慢

解決:

a.加索引

b.子查詢儘量縮小搜索範圍,減少join的次數

c.能用join就不要用in

d.加大查詢時間 queryTimeOut

我們這邊加大了queryTimeOut時間,然後報錯:Lock wait timeout exceeded; try restarting transaction

通過排查,發現是在執行更新操作的時候,一直在等待鎖。

select * from information_schema.innodb_trx;
select * from information_schema.innodb_locks;
select * from  information_schema.INNODB_LOCK_WAITS;
SELECT * from information_schema.`PROCESSLIST`;
SHOW FULL PROCESSLIST;

當發現一直在佔用鎖的事物鎖,kill掉。
kill id

排查發現:佔用的鎖的語句,就是正在執行的更新語句。 這個是不對的。

繼續排查,發現方法中使用了事物,該事務綁定的是sql連接池。

執行順序是:

事物開始:

操作A進行了該行語句的更新

操作B(我的語句)執行該行語句的更新(該操作是自己建立的sql連接對象操作)

事物結束

這個時候,大家都發現問題了吧。

操作B必須要等到操作A事物提交,才能拿到行級鎖。

修改:

方案1:

將操作B也使用sql連接池的連接,進行數據庫操作

方案2:

將操作A進行修改,改成使用自己建立的sql連接來處理。

總結:

出現該問題的時候,肯定是有其它地方佔用了鎖,問題的解決點:需要先釋放鎖或者報錯所有的操作,在同一個事物中。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章