1. 程式人生 > >MySQL事務鎖問題-Lock wait timeout exceeded

MySQL事務鎖問題-Lock wait timeout exceeded

sta ESS kong -- function 一個 關系 ODB info

轉載:https://cloud.tencent.com/developer/article/1356959

問題現象:

  接口響應時間超長,耗時幾十秒才返回錯誤提示,後臺日誌中出現Lock wait timeout exceeded; try restarting transaction的錯誤

問題場景:

  1、在同一事務內先後對同一條數據進行插入和更新操作;

  2、多臺服務器操作同一數據庫;

  3、瞬時出現高並發現象;

問題原因:

  1、在高並發的情況下,Spring事物造成數據庫死鎖,後續操作超時拋出異常。

  2、Mysql數據庫采用InnoDB模式,默認參數:innodb_lock_wait_timeout設置鎖等待的時間是50s,一旦數據庫鎖超過這個時間就會報錯

解決方法:

1、查看數據庫當前的進程,看一下有無正在執行的慢SQL記錄線程。

mysql> show  processlist;

2、查看當前的事務

當前運行的所有事務

mysql> SELECT * FROM information_schema.INNODB_TRX;

當前出現的鎖

mysql> SELECT * FROM information_schema.INNODB_LOCKs;

鎖等待的對應關系

mysql> SELECT * FROM information_schema.INNODB_LOCK_waits;

解釋:看事務表INNODB_TRX,裏面是否有正在鎖定的事務線程,看看ID是否在show processlist裏面的sleep線程中,如果是,就證明這個sleep的線程事務一直沒有commit或者rollback而是卡住了,我們需要手動kill掉。

搜索的結果是在事務表發現了很多任務,這時候最好都kill掉。

3、批量刪除事務表中的事務

我這裏用的方法是:通過information_schema.processlist表中的連接信息生成需要處理掉的MySQL連接的語句臨時文件,然後執行臨時文件中生成的指令。

mysql>  select concat(‘KILL ‘,id,‘;‘) from information_schema.processlist where user=‘cms_bokong‘;
+------------------------+
| concat(‘KILL ‘,id,‘;‘) |
+------------------------+
| KILL 10508;            |
| KILL 10521;            |
| KILL 10297;            |
+------------------------+
18 rows in set (0.00 sec)

當然結果不可能只有3個,這裏我只是舉例子。參考鏈接上是建議導出到一個文本,然後執行文本。而我是直接copy到記事本處理掉 ‘|’,粘貼到命令行執行了。都可以。

kill掉以後再執行SELECT * FROM information_schema.INNODB_TRX; 就是空了。

這時候系統就正常了

故障排查

  1. mysql都是autocommit配置mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 0 | +--------------+ 1 row in set (0.00 sec)

如果是0 ,則改為1

mysql> set global autocommit=1;

  1. mysql的引擎檢查,可以檢查一下數據庫引擎是不是InnoDB(mysql5.5.5以前默認是MyISAM,mysql5.5.5以後默認是InnoDB)show ENGINES; #檢查命令 如果不是的話改為 InnoDB :

查看表使用的存儲引擎

show table status from db_name where name=‘table_name‘;

修改表的存儲引擎

alter table table_name engine=innodb;

MySQL事務鎖問題-Lock wait timeout exceeded