最近做了一個定時任務(wù)的項目, 因為多個定時任務(wù)在一個時間點同時進行, 從而產(chǎn)生了鎖等待超時的問題;
產(chǎn)生問題原因:
A,B兩個定時任務(wù), 操作的同一張表; 并且兩個任務(wù)同時觸發(fā);
業(yè)務(wù)邏輯都是先刪除表中數(shù)據(jù), 然后再新增數(shù)據(jù), AB操作的不是同一條數(shù)據(jù);
A業(yè)務(wù)處理速度快, 先拿到了該表的鎖, B后面才拿到
但是由于我們數(shù)據(jù)庫的表超時時間比較短, 導(dǎo)致A表操作沒有結(jié)束, B表等待時間已經(jīng)超時, 從而拋出了異常;
解決方案:
- 修改定時任務(wù)執(zhí)行時間, 讓兩個任務(wù)有足夠的錯開時間
優(yōu)點:
(1). 無代碼邏輯修改, 解決問題方便
缺點:
(1). 定時任務(wù)的運行時間可能與業(yè)務(wù)強相關(guān)
(2). 該時間不太容易掌控, - 修改mysql鎖等待時間
優(yōu)點:
(1). 無需修改代碼, 修改方便,
(2). 試用該數(shù)據(jù)庫所有表
缺點:
(1). 有些公司對數(shù)據(jù)庫管理嚴(yán)格, 審批繁瑣, 可能不允許修改;
(2). 修改鎖等待時間不容易掌控, 可能滿足現(xiàn)狀后續(xù)又要調(diào); - 使用行級鎖, 避免表鎖(推薦)
優(yōu)點:
(1). 適應(yīng)能力強, 數(shù)據(jù)之間無干擾
缺點:
(1). 編碼時需要注意sql對索引的使用
使用方法:
在編寫sql時, 刪除/修改走索引或者唯一主鍵(例如id), 注意使用時防止索引失效;
(InnoDB的行鎖是針對索引加的鎖毕谴,不是針對記錄加的鎖。并且該索引不能失效,否則都會從行鎖升級為表鎖。)
一些關(guān)于表能用到的命令
# 查詢?nèi)值却聞?wù)鎖超時時間
SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout';
#查看執(zhí)行計劃
show processlist;
#鎖查詢
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;