死鎖發(fā)生的條件:
1浅缸、資源不能共享,需要只能由一個進(jìn)程或者線程使用
2、請求且保持鞋拟,已經(jīng)鎖定的資源自給保持著不釋放
3骂维、不剝奪,自給申請到的資源不能被別人剝奪
4贺纲、循環(huán)等待
死鎖的預(yù)防
防止死鎖的途徑就是避免滿足死鎖條件的情況發(fā)生航闺,為此用戶需要遵循以下原則。
(1)盡量避免并發(fā)地執(zhí)行涉及到修改數(shù)據(jù)的語句猴誊。 【這個應(yīng)該是能想到的潦刃,但是確實沒想到】
(2)要求每個事務(wù)一次就將所有要使用的數(shù)據(jù)全部加鎖,否則就不予執(zhí)行懈叹。 【這個應(yīng)該是能想到的福铅,但是確實沒想到】
(3)預(yù)先規(guī)定一個封鎖順序,所有的事務(wù)都必須按這個順序?qū)?shù)據(jù)執(zhí)行封鎖项阴。如不同的過程在事務(wù)內(nèi)部對對象的更新執(zhí)行順序應(yīng)盡量保持一致滑黔。
(4)每個事務(wù)的執(zhí)行時間不可太長,在業(yè)務(wù)允許的情況下可以考慮將事務(wù)分割成為幾個小事務(wù)來執(zhí)行环揽÷缘矗【比如說把復(fù)雜的多表查詢分散成多次單表查詢】
(5)數(shù)據(jù)存儲空間離散法。數(shù)據(jù)存儲空間離散法是指采取各種手段歉胶,將邏輯上在一個表中的數(shù)據(jù)分散到若干離散的空間上去汛兜,以便改善對表的訪問性能。主要通過將大表按行或列分解為若干小表通今,或者按不同的用戶群分解兩種方法實現(xiàn)粥谬。這種方法類似分散“數(shù)據(jù)熱點”,但是確實辫塌,如果數(shù)據(jù)不是太經(jīng)常被訪問漏策,那么死鎖就不會太經(jīng)常發(fā)生。
(6)還是類似(1)的臼氨,比如有一個修改上百條記錄的update語句掺喻,我們可以修改成每10條一個update語句,或者干脆就每條記錄一個update語句储矩。
(7)將經(jīng)常更新的數(shù)據(jù)庫和查詢數(shù)據(jù)庫分開
死鎖的產(chǎn)生實例
mysql的InnoDB中感耙,鎖是通過加在索引上實現(xiàn)的。
下面的例子講述了一個mysql在innodb的索引上死鎖的發(fā)生過程持隧。
在圖中即硼,session1為了第一次更新,鎖住了b=2 and c=3這個索引節(jié)點屡拨。
在session2中只酥,為了更新题诵,必須等待session1釋放鎖。
然后session1再請求一次更新层皱,那么數(shù)據(jù)庫就會檢測到死鎖的存在,不會等待timeout了赠潦,直接返回叫胖。