關於數據庫鎖的相關知識

大家以前可能都聽說或者瞭解過數據庫鎖的相關知識,爲什麼需要鎖呢,鎖又是什麼呢?下面我會詳細的給大家講一講。
數據庫鎖出現的目的:處理併發問題

併發問題是什麼?
我們都知道數據庫可能會被同時大量訪問,這時假如第一個線程訪問並修改了我們的數據庫某個字段,第二個線程訪問也修改了這個字段,那麼就造成了同時訪問問題,這時由於他們都修改了數據庫,那麼就會造成髒數據問題,第一個線程訪問並修改的數據被覆蓋掉了。
爲了防止這種情況發生,我們就發明這個技術,當一個事務訪問數據庫時,鎖會將所修改的表鎖起來,另一個事務沒有辦法同時對這個表進行修改,這時就達到了我們的目的,不會產生髒數據。
那麼鎖的分類是什麼呢?如下所示:

一.樂觀鎖:
樂觀鎖是指我們假設數據一般情況下不會造成衝突,當要進行數據提交更新的時候,我們纔會對數據進行檢測,然後將結果返回給用戶,讓用戶決定該如何去處理。樂觀鎖並不是數據庫的一種額外機制,它只是依靠數據本身來對數據是否修改來進行了檢測判斷。

樂觀鎖實現:
1.依靠原有字段來實現樂觀鎖:比如有個字段是商品庫存,事務一先查詢庫存數,查出來是3,這時候事務二對商品庫存進行了修改,變成了2,這時候事務一打算更新數據,再次進行查詢了商品庫存,發現跟它取數據的時候的庫存數不一樣,這時候就會返回給提交人一條信息,告訴他已經發生改變,是否繼續執行原有修改操作。

2.依靠原有字段不會改變表結構,但是會有一種嚴重的ABA問題,就是說剛纔情境下事務二將其變爲2後再改成了3,這種情況下並不是說數據就沒有發生修改,這個過程其實是有問題的。那我們要如何處理這種情況呢?我們可以多加一個版本字段version,每當修改一次數據,這個字段會自動加一,這樣就很合理了,不會出現剛纔的ABA問題。但是其會改變表結構,所以還是要均衡考慮。當然,時間戳也是這種情況下的一種體現,其天然的自增性使其也非常合適。

但是樂觀鎖存在一個高併發下的問題,當數據處於高併發情況下,比如淘寶這種網站,樂觀鎖會使事務頻繁操作失敗,這對於用戶來說一點也不友好,相對於悲觀鎖那種只要加上鎖基本就能更新成功來說,樂觀鎖失敗概率是很高的。當然我們也會有一定手段可以來降低失敗概率,比如優化SQL,使用庫存遞減等方式來實現。

二.悲觀鎖:
悲觀鎖爲什麼悲觀?因爲它實際上是一種"先取鎖再訪問"的方式,爲什麼這樣呢?因爲它假設我每次訪問數據時都會遇到別的事務來對我取得數據產生了影響,所以我需要提前加鎖,來保證別的事務對我操作的數據不能產生任何影響。

  1. 共享鎖(S鎖)
    共享鎖是指多個事務可以對一個共享頁上鎖,但是隻能讀共享頁中的內容,任何事務都不能修改共享頁中的內容,在該頁被讀取完畢時,S鎖立刻被釋放。
  2. 排它鎖(X鎖)
    排他鎖只能被一個數據庫事務封鎖此頁,其他的事務無法再對此頁上鎖,相當於事務獨佔了此數據頁。
  3. 更新鎖(U鎖)
    更新鎖是對共享鎖的改進,其用於來預定封鎖數據頁,一般來說,想要修改某個數據,會先給數據頁加上S鎖,然後等待別的事務將所有的S鎖釋放,然後自己升級爲X鎖,但是這樣有一個問題,假如多個事務同時對一個資源加上了 S鎖,都需要修改數據,那麼他們都要升級爲X鎖,所以他們都在等待對方先將S鎖釋放,這樣就造成了“死鎖”問題,所以爲了解決這個問題,就產生了U鎖,U鎖可以和S鎖共存,但是它們共存時只有U鎖能升級爲X鎖,S鎖在它面前只能選擇釋放資源,並且一個資源同時只能存在一把U鎖,這樣就完美解決了死鎖問題。

那悲觀鎖的優點和缺點在哪裏呢?
優點:
優點肯定是非常明顯的,悲觀鎖確保了數據的安全性,因爲同一個數據同時只能有一個事務在進行操作,所以其數據非常安全。

缺點:
悲觀鎖是數據庫的一種機制,所以肯定會產生額外的性能開銷,並且會增加產生死鎖的機會,並且會降低並行性,因爲同一個數據在同時只能有一個事務在進行數據處理。

應用場景:
1.樂觀鎖經常使用,特別是在高併發等場景下。
2.悲觀鎖使用的很少,在必須保護數據安全且併發較少的情況下用到,不過現在生產環境已經較少用到了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章