死鎖
指兩個或者兩個以上的事務(wù)在執(zhí)行過程中,因爭奪鎖資源而造成的一種互相等待的現(xiàn)象伺绽。
死鎖產(chǎn)生的必要條件
互斥
- 并發(fā)執(zhí)行的事務(wù)為了進行必要的隔離保證執(zhí)行正確养泡,在事務(wù)結(jié)束前,需要對修改的數(shù)據(jù)庫記錄持鎖奈应,保證多個事務(wù)對相同數(shù)據(jù)庫記錄串行修改澜掩。
串行修改:a 事務(wù)尚未提交,b 事務(wù)不能修改同個數(shù)據(jù)記錄
- 對于大型并發(fā)系統(tǒng)無法避免
請求與保持
- 已經(jīng)持有一個鎖資源杖挣,等待另外一個鎖資源
- 死鎖僅發(fā)生在請求兩個或兩個以上的鎖對象
- 由于應(yīng)用需要肩榕,難以消除
不剝奪
- 已經(jīng)獲得鎖資源的事務(wù),在未執(zhí)行前惩妇,不能被強制剝奪株汉,只能使用完時,由事務(wù)自己釋放歌殃。
- 一般用于已經(jīng)出現(xiàn)死鎖時乔妈,通過破壞該條件達到解除死鎖的目的。
- 數(shù)據(jù)庫系統(tǒng)通常通過一定的死鎖檢測機制發(fā)現(xiàn)死鎖挺份,強制回滾代價相對較小的事務(wù)褒翰,達到解除死鎖的目的。
環(huán)路等待
- 發(fā)生死鎖時匀泊,必然存在一個事務(wù)---鎖的環(huán)形鏈
- 按照同一順序獲取鎖,可以破壞該條件
- 通過分析死鎖事務(wù)之間的鎖競爭關(guān)系朵你,調(diào)整 SQL 的順序各聘,達到消除死鎖的目的。
MySQL 中的鎖
排他鎖
與其他任何鎖都是沖突的抡医。
共享鎖
多個事務(wù)可以共享一把鎖躲因。
加鎖方式
外部加鎖
由應(yīng)用程序執(zhí)行特定語句早敬,顯式的加鎖;
- 可以通過分析 sql 語句大脉,比較容易看清鎖的依賴關(guān)系
- 共享鎖
select * from table lock in share mode
- 排他鎖
select * from table for update
內(nèi)部加鎖
為了實現(xiàn) ACID 特性搞监,由數(shù)據(jù)庫內(nèi)部自動添加
- 加鎖規(guī)則繁瑣,與 SQL 執(zhí)行計劃镰矿、事務(wù)隔離級別琐驴、表索引結(jié)果有關(guān),不容易排查死鎖情況
哪些 SQL 需要持有鎖
-
快照讀
- 所有 select 語句都屬于快照讀
- Innodb 實現(xiàn)了多版本控制(MVCC)秤标,支持不加鎖的快照度 「保證 select 語句的性能」
- 能夠保證同一個 select 結(jié)果集一致
- 不能保證同一個事務(wù)內(nèi)部绝淡,select 語句和其他語句的數(shù)據(jù)一致性,如有業(yè)務(wù)需要苍姜,需外部顯式加鎖
-
當前讀
- select * from table lock in share mode
- select * from table for update
- Update from table set ...
- Insert into ...
- Delete from table ...
顯式加鎖的讀牢酵,以及更新插入刪除操作語句,都是可觸發(fā) MySQL 內(nèi)部加鎖的
捕獲死鎖的 sql 語句
sql 語句:
show engine innodb status