深入理解樂觀鎖與悲觀鎖

来源:https://www.cnblogs.com/xieyiyanjiu/archive/2019/04/23/10755476.html
-Advertisement-
Play Games

在資料庫的鎖機制中介紹過,資料庫管理系統(DBMS)中的併發控制的任務是確保在多個事務同時存取資料庫中同一數據時不破壞事務的隔離性和統一性以及資料庫的統一性。 樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。 無論是悲觀鎖還是樂觀鎖,都是人們定義出來的概念,可以認為是一種 ...


在資料庫的鎖機制中介紹過,資料庫管理系統(DBMS)中的併發控制的任務是確保在多個事務同時存取資料庫中同一數據時不破壞事務的隔離性和統一性以及資料庫的統一性。

樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。

無論是悲觀鎖還是樂觀鎖,都是人們定義出來的概念,可以認為是一種思想。其實不僅僅是關係型資料庫系統中有樂觀鎖和悲觀鎖的概念,像memcache、hibernate、tair等都有類似的概念。

針對於不同的業務場景,應該選用不同的併發控制方式。所以,不要把樂觀併發控制和悲觀併發控制狹義的理解為DBMS中的概念,更不要把他們和數據中提供的鎖機制(行鎖、表鎖、排他鎖、共用鎖)混為一談。其實,在DBMS中,悲觀鎖正是利用資料庫本身提供的鎖機制來實現的。

下麵來分別學習一下悲觀鎖和樂觀鎖。

悲觀鎖

在關係資料庫管理系統里,悲觀併發控制(又名“悲觀鎖”,Pessimistic Concurrency Control,縮寫“PCC”)是一種併發控制的方法。它可以阻止一個事務以影響其他用戶的方式來修改數據。如果一個事務執行的操作都某行數據應用了鎖,那隻有當這個事務把鎖釋放,其他事務才能夠執行與該鎖衝突的操作。
悲觀併發控制主要用於數據爭用激烈的環境,以及發生併發衝突時使用鎖保護數據的成本要低於回滾事務的成本的環境中。

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

在資料庫中,悲觀鎖的流程如下:

在對任意記錄進行修改前,先嘗試為該記錄加上排他鎖(exclusive locking)。

如果加鎖失敗,說明該記錄正在被修改,那麼當前查詢可能要等待或者拋出異常。 具體響應方式由開發者根據實際需要決定。

如果成功加鎖,那麼就可以對記錄做修改,事務完成後就會解鎖了。

其間如果有其他對該記錄做修改或加排他鎖的操作,都會等待我們解鎖或直接拋出異常。

MySQL InnoDB中使用悲觀鎖

要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性,因為MySQL預設使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。set autocommit=0;

//0.開始事務
begin;/begin work;/start transaction; (三者選一就可以)
//1.查詢出商品信息
select status from t_goods where id=1 for update;
//2.根據商品信息生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status為2
update t_goods set status=2;
//4.提交事務
commit;/commit work;

  

上面的查詢語句中,我們使用了select…for update的方式,這樣就通過開啟排他鎖的方式實現了悲觀鎖。此時在t_goods表中,id為1的 那條數據就被我們鎖定了,其它的事務必須等本次事務提交之後才能執行。這樣我們可以保證當前的數據不會被其它事務修改。

上面我們提到,使用select…for update會把數據給鎖住,不過我們需要註意一些鎖的級別,MySQL InnoDB預設行級鎖。行級鎖都是基於索引的,如果一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住,這點需要註意。

優點與不足

悲觀併發控制實際上是“先取鎖再訪問”的保守策略,為數據處理的安全提供了保證。但是在效率方面,處理加鎖的機制會讓資料庫產生額外的開銷,還有增加產生死鎖的機會;另外,在只讀型事務處理中由於不會產生衝突,也沒必要使用鎖,這樣做只能增加系統負載;還有會降低了並行性,一個事務如果鎖定了某行數據,其他事務就必須等待該事務處理完才可以處理那行數

樂觀鎖

在關係資料庫管理系統里,樂觀併發控制(又名“樂觀鎖”,Optimistic Concurrency Control,縮寫“OCC”)是一種併發控制的方法。它假設多用戶併發的事務在處理時不會彼此互相影響,各事務能夠在不產生鎖的情況下處理各自影響的那部分數據。在提交數據更新之前,每個事務會先檢查在該事務讀取數據後,有沒有其他事務又修改了該數據。如果其他事務有更新的話,正在提交的事務會進行回滾。樂觀事務控制最早是由孔祥重(H.T.Kung)教授提出。

樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設認為數據一般情況下不會造成衝突,所以在數據進行提交更新的時候,才會正式對數據的衝突與否進行檢測,如果發現衝突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。

相對於悲觀鎖,在對資料庫進行處理的時候,樂觀鎖並不會使用資料庫提供的鎖機制。一般的實現樂觀鎖的方式就是記錄數據版本。

數據版本,為數據增加的一個版本標識。當讀取數據時,將版本標識的值一同讀出,數據每更新一次,同時對版本標識進行更新。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本信息與第一次取出來的版本標識進行比對,如果資料庫表當前版本號與第一次取出來的版本標識值相等,則予以更新,否則認為是過期數據。

實現數據版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。

使用版本號實現樂觀鎖

使用版本號時,可以在數據初始化時指定一個版本號,每次對數據的更新操作都對版本號執行+1操作。並判斷當前版本號是不是該數據的最新的版本號。

1.查詢出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根據商品信息生成訂單
3.修改商品status為2
update t_goods 
set status=2,version=version+1
where id=#{id} and version=#{version};

優點與不足

樂觀併發控制相信事務之間的數據競爭(data race)的概率是比較小的,因此儘可能直接做下去,直到提交的時候才去鎖定,所以不會產生任何鎖和死鎖。但如果直接簡單這麼做,還是有可能會遇到不可預期的結果,例如兩個事務都讀取了資料庫的某一行,經過修改以後寫回資料庫,這時就遇到了問題。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、查看是否安裝mysql 什麼都沒顯示,說明沒有安裝 二、進入到opt目錄下,使用wget下載官方yum源的rpm包 三、安裝啟動mysql yum安裝: 然後會提示輸入y,輸入即可,安裝完成如下 啟動mysql服務: 查看mysql狀態: 關閉mysql服務: 開機啟動: 重啟systemctl ...
  • 摘要: 下文講述將"sql數值型"類型數值轉換為指定小數位的數據 方法1:採用 cast 方式轉換數值類型至指定小數位: 方法2:採用 convert 方式轉換數值類型至指定小數位: 參閱:http://www.maomao365.com/?p=6220 ...
  • 資料庫設計 物理設計: 選擇合適的資料庫管理系統。 考慮因素:成本,業務場景,開發語言,功能,操作系統等。 選擇合適的資料庫管理系統。 考慮因素:成本,業務場景,開發語言,功能,操作系統等。 Oracle 2.定義資料庫,表及欄位,要符合命名規範。 選擇存儲引擎:這裡以MySQL為例 選擇存儲引擎: ...
  • 1. 備份與還原的基礎說明 我們知道在DBA的日常工作中,SQL Server 資料庫的恢復請求偶有發生,可能是用作數據的追蹤,可也可能能是資料庫的災難恢復。 資料庫常用的備份命令如下: 備份文件的命名格式為:資料庫名字_備份類型(Full或Diff或Trn的一種)_時間格式.文件類型(bak或tr ...
  • 1、通過yum安裝: yum install redis 2、設置redis.conf中daemonize為yes。設置密碼: requirepass 3、安裝完後的啟動腳本是完善的,/etc/init.d/redis,不需要再另外操作。 查看啟動列表: chkconfig --list 安裝完可以 ...
  • --語 句 功 能--數據操作SELECT --從資料庫表中檢索數據行和列INSERT --向資料庫表添加新數據行DELETE --從資料庫表中刪除數據行UPDATE --更新資料庫表中的數據 --數據定義 CREATE TABLE --創建一個資料庫表DROP TABLE --從資料庫中刪除表 A ...
  • 由於資料庫存的是整個字元串組到一起了,C#代碼是這個樣子的。 在sqlserver中存儲的實際值是:20190416124941。那麼直接轉換? 所以在sqlserver中查詢的時候我們要進行轉化,因為在mssql中進行轉換需要是有標準的 例如/ : 等符號。那麼我們就進行截取吧。 最後就完事了。 ...
  • 加鎖的主要目的是為了防止併發操作時導致的數據不一致等問題,鎖分為共用鎖(S)、更新鎖(U)、排他鎖(X),共用鎖與更新只是單向相容?傳說中的單相思? 事務 事務能保證數據操作的原子性,要麼內部操作都提交,要麼都回退。事務內部某個地方出錯時,可以回滾前面的操作,比如更新、刪除等。 共用鎖 共用鎖允許並 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...