從悲觀鎖和樂觀鎖的角度怎麼避免死鎖

2022-03-22 22:21:26 字數 2189 閱讀 1656

當我們使用共享鎖的時候會出現死鎖的風險,比如

首先客戶端 1 開啟事務,然後採用讀鎖的方式對user_id=912178的資料行進行查詢,這時事務沒有提交的時候,這兩行資料行上了讀鎖。

當我們執行的時候客戶端 2 會一直等待,因為客戶端 1 也獲取了該資料的讀鎖,不需要客戶端 2 對該資料進行修改。這時客戶端 2 會提示等待超時,重新執行事務。

你能看到當有多個事務對同一資料獲得讀鎖的時候,可能會出現死鎖的情況。

如果從程式設計師的視角來看鎖的話,可以將鎖分成樂觀鎖和悲觀鎖,從名字中也可以看出這兩種鎖是兩種看待資料併發的思維方式。

樂觀鎖(optimistic locking)認為對同一資料的併發操作不會總發生,屬於小概率事件,不用每次都對資料上鎖,也就是不採用資料庫自身的鎖機制,而是通過程式來實現。在程式上,我們可以採用版本號機制或者時間戳機制實現。

在表中設計乙個版本字段 version,第一次讀的時候,會獲取 version 欄位的取值。然後對資料進行更新或刪除操作時,會執行update ... set version=version+1 where version=version。此時如果已經有事務對這條資料進行了更改,修改就不會成功。

這種方式類似我們熟悉的 svn、cvs 版本管理系統,當我們修改了**進行提交時,首先會檢查當前版本號與伺服器上的版本號是否一致,如果一致就可以直接提交,如果不一致就需要更新伺服器上的最新**,然後再進行提交。

時間戳和版本號機制一樣,也是在更新提交的時候,將當前資料的時間戳和更新之前取得的時間戳進行比較,如果兩者一致則更新成功,否則就是版本衝突。

你能看到樂觀鎖就是程式設計師自己控制資料併發操作的許可權,基本是通過給資料行增加乙個戳(版本號或者時間戳),從而證明當前拿到的資料是否最新。

悲觀鎖(pessimistic locking)也是一種思想,對資料被其他事務的修改持保守態度,會通過資料庫自身的鎖機制來實現,從而保證資料操作的排它性。

從這兩種鎖的設計思想中,你能看出樂觀鎖和悲觀鎖的適用場景:

樂觀鎖適合讀操作多的場景,相對來說寫的操作比較少。它的優點在於程式實現,不存在死鎖問題,不過適用場景也會相對樂觀,因為它阻止不了除了程式以外的資料庫操作。

悲觀鎖適合寫操作多的場景,因為寫的操作具有排它性。採用悲觀鎖的方式,可以在資料庫層面阻止其他事務對該資料的操作許可權,防止讀 - 寫和寫 - 寫的衝突。

在客戶端 1 獲取某資料行共享鎖的同時,另乙個客戶端 2 也獲取了該資料行的共享鎖,這時任何乙個客戶端都沒法對這個資料進行更新,因為共享鎖會阻止其他事務對資料的更新,當某個客戶端想要對鎖定的資料進行更新的時候,就出現了死鎖的情況。當死鎖發生的時候,就需要乙個事務進行回滾,另乙個事務獲取鎖完成事務,然後將鎖釋放掉,很像交通堵塞時候的解決方案。

避免死鎖

1、以固定的順序訪問表和行。比如兩個更新資料的事務,事務a 更新資料的順序 為1,2;事務b更新資料的順序為2,1。這樣更可能會造成死鎖。

2、大事務拆小。大事務更傾向於死鎖,如果業務允許,將大事務拆小。

3、在同乙個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖概率。

4、降低隔離級別。如果業務允許,將隔離級別調低也是較好的選擇,比如將隔離級別從rr調整為rc,可以避免掉很多因為gap鎖造成的死鎖。

5、為表新增合理的索引。可以看到如果不走索引將會為表的每一行記錄新增上鎖,死鎖的概率大大增大。

6、業務上盡量將加鎖的操作後移,降低鎖時間。

7、調整innodb_lock_wait_timeout引數。預設是50,即等待50秒還未獲取鎖,當前語句報錯,一般設定20-30

8、主動死鎖檢測,innodb_deadlock_detect,5.7後預設開啟,但在高併發業務下會影響應能,建議關閉,調整innodb_lock_wait_timeout

當然在資料庫中,也有一些情況是不會發生死鎖的,比如採用樂觀鎖的方式。另外在 mysql myisam 儲存引擎中也不會出現死鎖,這是因為 myisam 總是一次性獲得全部的鎖,這樣的話要麼全部滿足可以執行,要麼就需要全部等待。

悲觀鎖和樂觀鎖

1.悲觀鎖,正如其名,它指的是對資料被外界 包括本系統當前的其他事務,以及來自外部系統的事務處理 修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制 也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無...

悲觀鎖和樂觀鎖

前幾天有人問了我乙個問題,說如果資料庫某些操作不用事務,那麼又需要保持資料的一致性,那麼該用什麼方法替代事務。我就想到了悲觀鎖和樂觀鎖的思想,下面我解釋一下在資料庫中的悲觀鎖和樂觀鎖 1.悲觀鎖就是把資料庫的一些操作,放在事務當中,依賴資料庫的隔離級別,實現對資料修改的封鎖,這樣做資料一致性可以保持...

悲觀鎖和樂觀鎖

悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。樂觀鎖 optim...