發(fā)生的原因
-
例子
例子
mysql 加上行鎖

行鎖導(dǎo)致的死鎖
什么是死鎖
死鎖是指兩個(gè)或者兩個(gè)以上的事務(wù)在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象。
死鎖產(chǎn)生的必要條件
-
互斥
- 并發(fā)執(zhí)行的事務(wù)為了進(jìn)行必要的隔離保證執(zhí)行正確,在事務(wù)結(jié)束前,需要對(duì)修改的數(shù)據(jù)庫(kù)記錄持鎖,保證多個(gè)事務(wù)對(duì)相同數(shù)據(jù)庫(kù)記錄串行修改。
- 對(duì)于大型并發(fā)系統(tǒng)無(wú)法避免。
-
請(qǐng)求與保持
- 已經(jīng)持有一個(gè)資源鎖,等待另外一個(gè)資源鎖
- 死鎖僅發(fā)生在請(qǐng)求兩個(gè)或者兩個(gè)以上的鎖對(duì)象的時(shí)候
- 由于應(yīng)用的需要,難以消除
-
不剝奪
- 已經(jīng)獲得鎖資源的事務(wù),在未執(zhí)行前,不能被強(qiáng)行剝奪,只能在使用完成后,由事務(wù)自己釋放。
- 一般用于已經(jīng)出現(xiàn)死鎖時(shí),通過(guò)破壞該條件達(dá)到解除死鎖的目的。
- 數(shù)據(jù)庫(kù)系統(tǒng)通常通過(guò)一定的死鎖檢測(cè)機(jī)制發(fā)現(xiàn)死鎖,強(qiáng)制回滾代價(jià)相對(duì)較小的事務(wù),達(dá)到解除死鎖的目的。
-
環(huán)路等待
環(huán)路等待- 發(fā)生死鎖時(shí),必然存在一個(gè)事務(wù) —— 鎖的環(huán)形鏈。
- 按照同一順序獲取鎖,可以破壞該條件。
- 通過(guò)分析死鎖事物之間的鎖競(jìng)爭(zhēng)關(guān)系,調(diào)整SQL的順序,達(dá)到消除死鎖的目的。
MySQL中的鎖
- X 排他鎖 與任何其他的鎖都是沖突的,其他的鎖需要等待
- S 共享鎖 與共享鎖可以兼容,如果有其他需要加共享鎖是可以進(jìn)行的
| 已有鎖 \ 欲加鎖 | X (排它鎖) | S (共享鎖) |
|---|---|---|
| X(排它鎖) | 沖突 | 沖突 |
| S(共享鎖) | 沖突 | 兼容 |
- 加鎖的方式:
- 外部加鎖:
- 由應(yīng)用程序添加,鎖依賴(lài)關(guān)系較容易分析
- 共享鎖(S): select * from table lock in share mode
- 排它鎖(X): select * from table for update
- 內(nèi)部加鎖:
- 為了實(shí)現(xiàn)ACID特性,由數(shù)據(jù)庫(kù)系統(tǒng)內(nèi)部自動(dòng)添加
- 加鎖規(guī)則繁瑣,與SQL執(zhí)行計(jì)劃、事務(wù)隔離級(jí)別、表索引結(jié)構(gòu)有關(guān)
- 共享鎖(S)和排它鎖(X)
- 外部加鎖:
哪些SQL需要持有鎖
- 快照讀:
- Innodb 實(shí)現(xiàn)了多版本控制(MVCC),支持不加鎖快照讀
- Select * from table where ……
- 能夠保證同一個(gè)Select結(jié)果集是一致的
- 不能保證同一個(gè)事務(wù)內(nèi)部,Select語(yǔ)句和其他語(yǔ)句的數(shù)據(jù)一致性,如果業(yè)務(wù)需要,需要通過(guò)外部顯示加鎖。
- 當(dāng)前讀:
- select * from table lock in share mode
- select * from table for update
- update from table set ……
- insert into ……
- delete from table ……
分析死鎖的常用辦法
-
show engine innodb status
分析死鎖


