參考連接:https://www.cnblogs.com/nicole-star/p/11114199.html
一、問題
### Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction;
現象:接口響應時間超長,耗時幾十秒才返回錯誤提示,后台日志中出現Lock wait timeout exceeded; try restarting transaction的錯誤
二、原因分析
使用InnoDB表類型的時候,鎖等待超過了innodb_lock_wait_timeout(默認是50s)設置的時間,所以報錯
三、可能出現場景
1、在同一事務內先后對同一條數據進行插入和更新操作
2、多台服務器操作同一數據庫
3、瞬時出現高並發現象,spring事務造成數據庫死鎖,后續操作超時拋出異常
4、事務A對記錄C進行更新/刪除操作的請求未commit時,事務B也對記錄C進行更新/刪除操作。此時,B會等A提交事務,釋放行鎖。當等待時間超過innodb_lock_wait_timeout設置值時,會產生“LOCK WAIT”事務。
四、解決方案
1、【治標方法】innodb_lock_wait_timeout 鎖定等待時間改大
my.ini文件:
#innodb_lock_wait_timeout = 50
修改為
innodb_lock_wait_timeout = 500
缺點:全局更改,影響也是全局的,等待時間加長,容易使等待事務增多導致堆積問題。
2、【治標方法】事務信息查詢
SELECT * FROM information_schema.innodb_trx
查到一個一直沒有提交的只讀事務(trx_state=”LOCK WAIT”),找到對應線程,執行:
kill 線程ID(trx_mysql_thread_id)
3、【治標方法】如果殺掉線程依然不能解決,可以查找執行線程耗時比較久的任務,kill掉
SELECT * from information_schema.`PROCESSLIST` WHERE Time > 1000 AND USER = 'xxx' ORDER BY TIME desc;
kill 線程ID
4、【根本解決方法!】找到鎖表的事務,分析鎖表原因,進行優化。
實例:司機APP進行運單簽收,需要對et_waybill_info表某些記錄進行更新操作。一直處於鎖等待狀態,直到超時報錯。
經排查,發現:系統定時器定時執行任務,將所有未標識亮的已裝車或簽收的運單,按批次處理,如果運單裝車了但長時間未上傳GPS、溫濕度等信息,會一直被定時器處理。數據量越積越大,隊列長時間等待,對et_waybill_info表鎖住沒有釋放,致使簽收要操作et_waybill_info表無法拿到鎖,進行數據操作。
臨時解決方案:停掉定時器任務
根本解決方案:優化定時器
五、預防措施
1、開始事務(@transtion)指定超時時 間
例:@Transactional( rollbackFor = Exception.class , isolation = Isolation.REPEATABLE_READ, timeout = 30)
2、事務中存在批量修改、刪除語句的時候,where條件盡量加索引
3、事務中存在批量修改、刪除語句的時候,盡可能減少事務的執行時間
4、減少並發線程數
六、相關信息
1、innodb_lock_wait_timeout和lock_wait_timeout
innodb_lock_wait_timeout:InnoDB事務等待一個行級鎖的時間最長時間(單位是秒),超過這個時間就會放棄。默認值是50秒
lock_wait_timeout:獲取元數據鎖的超時時間。這個適合用於除了系統表之外的所有表(mysql庫之外)。
區別於innodb_lock_wait_timeout是針對dml操作的行級鎖的等待時間 ,而lock_wait_timeout是數據結構ddl操作的鎖的等待時間
2、事務相關表
INNODB_TRX 當前運行的所有事務
INNODB_LOCKS 當前出現的鎖,查看正在鎖的事務
INNODB_LOCK_WAITS 鎖等待的對應關系,查看等待鎖的事務
3、information_schema和performance_schema
information_schema:對數據庫元數據的抽象分析,由此提供了SQL語句方式來查詢數據庫運行時狀態,每次對infomation_schema的查詢都產生對metadata的互斥訪問,影響其他數據庫的訪問性能。這張數據表保存了MySQL服務器所有數據庫的信息。如數據庫名,數據庫的表,表欄的數據類型與訪問權限等。
performance_schema:內存型數據庫,使用performance_schema存儲引擎,通過事件機制將mysql服務的運行時狀態采集並存儲在performance_schema數據庫。用於監控MySQL server在一個較低級別的運行過程中的資源消耗、資源等待等情況。
七、總結
1、當看到mysql報錯時,可以根據報錯的信息及錯誤號去分析報錯原因,然后冷靜分析,透過現象看本質,從根本上解決問題。少用治標不治本的方案,還可能會帶來其他問題。
2、了解了mysql里幾張事務相關表
3、初識information_schema和performance_schema