Mybatis關聯對映(一對一)
問題現象:
介面響應時間超長,耗時幾十秒才返回錯誤提示,後臺日誌中出現Lock wait timeout exceeded; try restarting transaction
的錯誤
問題場景:
1、在同一事務內先後對同一條資料進行插入和更新操作;
2、多臺伺服器操作同一資料庫;
3、瞬時出現高並發現象;
問題原因:
1、在高併發的情況下,Spring事物造成資料庫死鎖,後續操作超時丟擲異常。
2、資料庫採用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;
就是空了。
這時候系統就正常了
故障排查
- mysql都是autocommit配置mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 0 | +--------------+ 1 row in set (0.00 sec)
如果是0 ,則改為1
mysql> set global autocommit=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;