最近生產出現一次死鎖問題,很棘手,望各位大佬相助分析一下死鎖產生原因
注:
ID主鍵自增
Status普通索引,可取值1初始,2程序中,3成功,4失敗,5過期
Priority普通索引,目前取值均為1
UniqueNumber唯一索引,32位md5值
1.InnoDB默認RR可重復讀級別
2.兩實體四個相同執行緒,執行緒執行順序如下
①
select
Content,Priority,UniqueNumber
from t
where (Status = 1 or Status = 4)
order by Priority
asc limit 0,100
for update
②
update t set Status = 2
where UniqueNumber = '32位md5'
③
若過期update Status = 5
若失敗update Status = 4
若成功update Status = 3
其中①②在同一事務中,因為①②所在同一方法加了@transaction注解
①②多執行緒串行,后面是多執行緒并行
查看mysql死鎖日志發現
①和②居然發生死鎖,如圖,實在想不明白
考慮了間隙鎖等原因,但在實際環境無法復現
求各位大佬幫忙復現一下,萬分感謝
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
陳述句①,你給status=1或4的前100行加上了寫鎖,而且這個鎖在事務結束后才會解開。If you use FOR UPDATE with a storage engine that uses page or row locks, rows examined by the query are write-locked until the end of the current transaction.
陳述句②,你想把UniqueNumber = '32位md5'的行的status列設為2。
因為存在UniqueNumber = '32位md5'且status=1or4的行已經被陳述句①上了寫鎖,所以陳述句②想要修改status時會死鎖。
我猜你的誤區可能是,認為陳述句①select Content,Priority,UniqueNumber 沒有選status啊,為什么就被鎖了呢。
這是因為Innoob支持行鎖,是把整行全部鎖掉,不可以只鎖某一行的某幾列。
uj5u.com熱心網友回復:
大佬你好,這種情況我嘗試過,這種情況mysql并沒有產生死鎖,是等待超時了,我知道InooDB默認行級鎖您可以看一下我的blink,,因為分不夠所以發不了帖子了。里面有一張死鎖日志圖片,①陳述句想獲取next-key鎖 ②陳述句想獲取插入意向鎖。實在搞不明白多執行緒情況下會發生這種情況。十分感謝!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/63900.html
標籤:MySQL
上一篇:安裝MySQL出現問題
下一篇:從體系結構談SQL優化初稿待完善
