悲觀鎖和樂觀鎖

2022-03-29 04:01:39 字數 2264 閱讀 9514

本質上,資料庫的樂觀鎖做法和悲觀鎖做法主要就是解決下面假設的場景,避免丟失更新問題:

乙個比較清楚的場景

下面這個假設的實際場景可以比較清楚的幫助我們理解這個問題:

假設當當網上使用者下單買了本書,這時資料庫中有條訂單號為001的訂單,其中有個status欄位是』有效』,表示該訂單是有效的;

後台管理人員查詢到這條001的訂單,並且看到狀態是有效的

使用者發現下單的時候下錯了,於是撤銷訂單,假設執行這樣一條sql: update order_table set status = 『取消』 where order_id = 001;

後台管理人員由於在b這步看到狀態有效的,這時,雖然使用者在c這步已經撤銷了訂單,可是管理人員並未重新整理介面,看到的訂單狀態還是有效的,於是點選」發貨」按鈕,將該訂單發到物流部門,同時執行類似如下sql,將訂單狀態改成已發貨:update order_table set status = 『已發貨』 where order_id = 001

其實之前已經分別對樂觀鎖的做法和悲觀鎖的做法做了詳細的分析,

這裡引用wiki的定義做更權威的引用說明

.本質上,這裡wiki的意思就是,悲觀鎖和樂觀鎖都是為了解決丟失更新問題或者是髒讀。悲觀鎖和樂觀鎖的重點就是是否在讀取記錄的時候直接上鎖。悲觀鎖的缺點很明顯,需要乙個持續的資料庫連線,這在web應用中已經不適合了。

觀點1:只有衝突非常嚴重的系統才需要悲觀鎖;

分析:這是更準確的說法;我在原文中說到:

「所有悲觀鎖的做法都適合於狀態被修改的概率比較高的情況,具體是否合適則需要根據實際情況判斷。」,表達的也是這個意思,不過說法不夠準確;的確,之所以用悲觀鎖就是因為兩個使用者更新同一條資料的概率高,也就是衝突比較嚴重的情況下,所以才用悲觀鎖。

觀點2:最後提交前作一次select for update檢查,然後再提交update也是一種樂觀鎖的做法

分析:這是更準確的說法;

*****除了上面的觀點1和觀點2是更準確的說法,下面的所有觀點都是錯誤的***********

觀點3:這個問題的原因是因為資料庫隔離級別是uncommitted read級別;

分析:這個觀點是錯誤的;

這個過程本身就是在read committed隔離級別下發生的,從a到d每一步,尤其是d這步,並不是因為讀到了未提交的資料,僅僅是因為使用者介面沒有重新整理[事實上也不可能做自動重新整理,這樣相當於資料庫一發生改變立刻要重新整理了,這需要監聽資料庫了,顯然這是簡單問題複雜化了];

觀點4:悲觀鎖是指乙個使用者在更新資料的時候,其他使用者不能讀取這條記錄;也就是update阻塞讀才叫悲觀鎖;

分析:這個觀點是錯的;

這在db2背景的開發中尤其常見;因為db2預設就是update會阻塞讀;但是這是各個資料庫對讀寫的時候上鎖的併發處理實現不一樣。但這根本不是悲觀鎖樂觀鎖的區別。oracle可以做到寫不阻塞讀僅僅是因為做了多版本併發控制(multiversion concurrency control),

但是在oracle裡面,一樣可以做樂觀鎖和悲觀鎖的控制。這本質上是應用層面的選擇。

觀點5:oracle實際上用的就是樂觀鎖

分析:這個觀點是錯的;

前面說了,oracle的確可以做到寫不阻塞讀,但是這不是悲觀鎖和樂觀鎖的問題。這是因為實現了多版本併發控制。按照wiki的定義,悲觀鎖和樂觀鎖是在應用層面選擇的。oracle的應用只要在第二步做了select for update,就是悲觀鎖的做法;

況且oracle在任何隔離級別下,除了分布式事務兩階段提交的短暫時間,其他所有情況下都不存在寫阻塞讀的情況,如果按照這個觀點的話那oracle已經不能做悲觀鎖了-_-

觀點6:不需要這麼麻煩,只需要在d這步,最後提交更新的時候再做乙個普通的select檢查一下就可以;[就是double check的做法]

分析:這個觀點是錯的。

這個做法其實在 傳統悲觀鎖做法的變通』這節已經說明了,如果要這麼做的話,仍然需要在最後提交更新前double check的時候做乙個select for update, 否則select結束到update提交前的時間仍然有可能記錄被修改;

觀點7:應該盡可能使用悲觀鎖;

分析:這個觀點是錯的;

a. 根據悲觀鎖的概念,使用者在讀的時候(b這步)就會將記錄鎖住,直到更新結束的時候才會將鎖釋放,所以整個鎖的過程時間比較長;

所以,現在大部分應用都應該是樂觀鎖的;

悲觀鎖和樂觀鎖

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

悲觀鎖和樂觀鎖

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

悲觀鎖和樂觀鎖

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