背景:現(xiàn)網(wǎng)報環(huán)境很慢,提交沒有響應(yīng)。
日志:Lock wait timeout exceeded; try restarting transaction
解決方法
1.查看數(shù)據(jù)庫當(dāng)前的進(jìn)程
mysql> show processlist;
看一下有無正在執(zhí)行的慢SQL記錄線程。
2.查看當(dāng)前的事務(wù)
#當(dāng)前運行的所有事務(wù)
mysql> SELECT * FROM information_schema.INNODB_TRX;
#當(dāng)前出現(xiàn)的鎖
mysql> SELECT * FROM information_schema.INNODB_LOCKs;
#鎖等待的對應(yīng)關(guān)系
mysql> SELECT * FROM information_schema.INNODB_LOCK_waits;
解釋:看事務(wù)表INNODB_TRX,里面是否有正在鎖定的事務(wù)線程,看看ID是否在show processlist里面的sleep線程中,如果是,就證明這個sleep的線程事務(wù)一直沒有commit或者rollback而是卡住了,我們需要手動kill掉。
搜索的結(jié)果是在事務(wù)表發(fā)現(xiàn)了很多任務(wù),這時候最好都kill掉。
3.批量刪除事務(wù)表中的事務(wù)
我這里用的方法是:通過information_schema.processlist表中的連接信息生成需要處理掉的MySQL連接的語句臨時文件,然后執(zhí)行臨時文件中生成的指令。
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)
當(dāng)然結(jié)果不可能只有3個,這里我只是舉例子。參考鏈接上是建議導(dǎo)出到一個文本,然后執(zhí)行文本。而我是直接copy到記事本處理掉 ‘|’,粘貼到命令行執(zhí)行了。都可以。
kill掉以后再執(zhí)行SELECT * FROM information_schema.INNODB_TRX;
就是空了。
這時候系統(tǒng)就正常了
3.故障排查(什么原因引起的)
3.1mysql都是autocommit配置
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
mysql>
如果是0 ,則改為1,set global autocommit=1;
3.2mysql的引擎檢查
,可以檢查一下數(shù)據(jù)庫引擎是不是InnoDB(mysql5.5.5以前默認(rèn)是MyISAM,mysql5.5.5以后默認(rèn)是InnoDB)
show ENGINES; #檢查命令
如果不是的話改為 InnoDB :
#查看表使用的存儲引擎
show table status from db_name where name='table_name';
#修改表的存儲引擎
alter table table_name engine=innodb;
為什么用InnoDB呢,參考 MYSQL的存儲引擎
我檢查后發(fā)現(xiàn)數(shù)據(jù)庫的配置都是符合要求的,那為什么還會事務(wù)失敗呢,只能分析數(shù)據(jù)庫語句了,使用慢查詢分析。參考 慢日志分析工具—mysqldumpslow 和 mysqlsla.