MySQL中悲觀鎖和樂觀鎖究竟是什麼?

索引和鎖是數據庫中的兩個核心知識點,隔離級別的實現都是經過鎖來完成的按照鎖顆粒對鎖進行劃分 ?程序員

鎖用來對數據進行鎖定,咱們能夠從鎖定對象的粒度大小來對鎖進行劃分,分別爲行鎖、頁鎖和表鎖。數據庫

  • 行鎖就是按照行的粒度對數據進行鎖定。鎖定力度小,發生鎖衝突機率低,能夠實現的併發度高,可是對於鎖的開銷比較大,加鎖會比較慢,容易出現死鎖狀況。併發

  • 頁鎖就是在頁的粒度上進行鎖定,鎖定的數據資源比行鎖要多,由於一個頁中能夠有多個行記錄。當咱們使用頁鎖的時候,會出現數據浪費的現象,但這樣的浪費最多也就是一個頁上的數據行。頁鎖的開銷介於表鎖和行鎖之間,會出現死鎖。鎖定粒度介於表鎖和行鎖之間,併發度通常。設計

  • 表鎖就是對數據表進行鎖定,鎖定粒度很大,同時發生鎖衝突的機率也會較高,數據訪問的併發度低。不過好處在於對鎖的使用開銷小,加鎖會很快。3d

還有區鎖和數據庫鎖.對象

 

 

每一個層級的鎖數量是有限制的,由於鎖會佔用內存空間,鎖空間的大小是有限的。當某個層級的鎖數量超過了這個層級的閾值時,就會進行鎖升級。鎖升級就是用更大粒度的鎖替代多個更小粒度的鎖,好比 InnoDB 中行鎖升級爲表鎖,這樣作的好處是佔用的鎖空間下降了,但同時數據的併發度也降低了。blog

 

從數據庫管理的角度對鎖進行劃分索引

共享鎖和排它鎖事件

  • 共享鎖也叫讀鎖或 S 鎖,共享鎖鎖定的資源能夠被其餘用戶讀取,但不能修改。在進行SELECT的時候,會將對象進行共享鎖鎖定,當數據讀取完畢以後,就會釋放共享鎖,這樣就能夠保證數據在讀取時不被修改。
    事務

  • 排它鎖也叫獨佔鎖、寫鎖或 X 鎖。排它鎖鎖定的數據只容許進行鎖定操做的事務使用,其餘事務沒法對已鎖定的數據進行查詢或修改。

當咱們對數據進行更新的時候,也就是INSERT、DELETE或者UPDATE的時候,數據庫也會自動使用排它鎖,防止其餘事務對該數據行進行操做。

 

意向鎖(Intent Lock),簡單來講就是給更大一級別的空間示意裏面是否已經上過鎖。

 

從程序員的角度對鎖進行劃分

樂觀鎖

樂觀鎖(Optimistic Locking)認爲對同一數據的併發操做不會總髮生,屬於小几率事件,不用每次都對數據上鎖,也就是不採用數據庫自身的鎖機制,而是經過程序來實現。在程序上,咱們能夠採用版本號機制或者時間戳機制實現。

  • 樂觀鎖的版本號機制

在表中設計一個版本字段 version,第一次讀的時候,會獲取 version 字段的取值。而後對數據進行更新或刪除操做時,會執行UPDATE ... SET version=version+1 WHERE version=version。此時若是已經有事務對這條數據進行了更改,修改就不會成功。

  • 樂觀鎖的時間戳機制

時間戳和版本號機制同樣,也是在更新提交的時候,將當前數據的時間戳和更新以前取得的時間戳進行比較,若是二者一致則更新成功,不然就是版本衝突。

 

悲觀鎖

悲觀鎖(Pessimistic Locking)也是一種思想,對數據被其餘事務的修改持保守態度,會經過數據庫自身的鎖機制來實現,從而保證數據操做的排它性。

適用場景

  • 樂觀鎖適合讀操做多的場景,相對來講寫的操做比較少。它的優勢在於程序實現,不存在死鎖問題,不過適用場景也會相對樂觀,由於它阻止不了除了程序之外的數據庫操做。

  • 悲觀鎖適合寫操做多的場景,由於寫的操做具備排它性。採用悲觀鎖的方式,能夠在數據庫層面阻止其餘事務對該數據的操做權限,防止讀 - 寫和寫 - 寫的衝突。

總結

樂觀鎖和悲觀鎖並非鎖,而是鎖的設計思想。

避免死鎖的發生:

    • 若是事務涉及多個表,操做比較複雜,那麼能夠儘可能一次鎖定全部的資源,而不是逐步來獲取,這樣能夠減小死鎖發生的機率;

    • 若是事務須要更新數據表中的大部分數據,數據表又比較大,這時能夠採用鎖升級的方式,好比將行級鎖升級爲表級鎖,從而減小死鎖產生的機率;

    • 不一樣事務併發讀寫多張數據表,能夠約定訪問表的順序,採用相同的順序下降死鎖發生的機率。

相關文章
相關標籤/搜索