Lock wait timeout exceeded; try restarting transaction問題解析
問題分析:Lock wait timeout exceeded; try restarting transaction問題解析
一、mysql死鎖及超時的原因
當在業務邏輯中看到這個錯誤,或者mysql中使用update語句更新數據報錯: Lock wait timeout exceeded; try restarting transaction。也就是遇到了mysql死鎖,等待資源,事務鎖的問題。
可能原因:意外處理沒有關閉連接,導致連接過多、或是要更新的表的鎖在其它線程手里、系統異常導致事務未提交,再次請求相同記錄等等。
InnoDB關于在出現鎖等待的時候,會根據參數innodb_lock_wait_timeout的配置(默認50s),判斷是否需要進行timeout的操作:
二、mysql死鎖排查思路
1、show full processlist 查詢當前數據庫全部線程
show full processlist 查詢當前數據庫全部線程
show engine innodb status 命令查看當前的數據庫請求,然后再判斷當前事務中鎖的情況
select * from information_schema.innodb_trx 查詢當前運行的全部事務
注:select * from information_schema.innodb_trx;
MySQL 5.5版本以上才可以用此方法,5.5版本以下會沒有這個表;[Err] 1109 - Unknown table ‘innodb_trx’ in information_schema
當中trx_mysql_thread_id為事務線程的id,參照show full processlist命令中的線程信息查看
如果數據庫中有鎖的話,LOCK WAIT的就是鎖等待的
此時你可以直接使用命令:kill 事務線程id 殺掉它。比如:kill 99999
沒有的話,找到Command 狀態是query 并且Time 時間很長的id)有時候一定程度上也能解決一定的問題。
再用 show full processlist 查詢當前數據庫全部線程,發現剛才的線程沒了。
但是一般這樣還是很難發現被鎖的行記錄問題所在
2、information_schema
information_schema這張數據表保存了MySQL服務器所有數據庫的信息。
我們可以用這三張表innodb_trx、innodb_locks、innodb_lock_waits,使用如下命令,簡單地監控當前的事務并分析可能存在的問題:
select * from information_schema.innodb_trx ( 當前運行的所有事務)
select * from information_schema.innodb_locks (當前出現的鎖)
select * from information_schema.innodb_lock_waits (鎖等待的對應關系)
注意:在8.0.13版本中
innodb_locks表由performance_schema.data_locks表所代替,
innodb_lock_waits表則由performance_schema.data_lock_waits表代替。
三張表具體信息:

其中比較常用的一些列:
-
trx_id:InnoDB存儲引擎內部唯一的事物ID
-
trx_status:當前事務的狀態
-
trx_status:事務的開始時間
-
trx_requested_lock_id:等待事務的鎖ID
-
trx_wait_started:事務等待的開始時間
-
trx_weight:事務的權重,反應一個事務修改和鎖定的行數,當發現死鎖需要回滾時,權重越小的值被回滾
-
trx_mysql_thread_id:MySQL中的進程ID,與show processlist中的ID值相對應
-
trx_query:事務運行的SQL語句
綜上大體可以清楚的找到等待的事務即沒有獲取鎖的事務,進一步調整業務邏輯代碼。
一些建議:
1、可以結合update語句,調整索引,讓update能唯一定位到數據行,盡量退化到行鎖粒度;
2、相關查詢語句增加索引,減少事物整體耗時;
3、避免長事務、可以降低@Transactional的粒度;
4、減少批處理數據量,規范業務邏輯流程,考慮異常事務回滾等問題
如何復現
1、在同一事務內先后對同一條數據進行插入和更新操作
2、多臺服務器或者多個線程操作同一數據庫
3、瞬時出現高并發現象,spring事務造成數據庫死鎖(更新操作),后續操作超時拋出異常
4、事務 1對記錄a進行更新/刪除操作的請求未commit時,事務2也對記錄a進行更新/刪除操作。此時,2會等1提交事務,釋放行鎖。當等待時間超過innodb_lock_wait_timeout設置值時,會產生“LOCK WAIT”事務。
登錄MySQL腳本從兩個不同的會話連接到服務器。
然后讓在兩個會話中運行下面的語句:
SET autocommit=0;
UPDATE TEST SET code = ‘11’ WHERE code = ‘22’;
10s后,第二個會話將失敗:
mysql> UPDATE TEST SET code = '1 ’ WHERE code = ‘2’;
1205 - Lock wait timeout exceeded; try restarting transaction
Time: 11.227s
原文鏈接:
https://blog.csdn.net/weixin_38361347/article/details/129279916
https://baijiahao.baidu.com/s?id=1765682206889762057&wfr=spider&for=pc
浙公網安備 33010602011771號