中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

數據庫并發控制選擇樂觀鎖還是悲觀鎖

發布時間:2022-01-15 16:27:51 來源:億速云 閱讀:184 作者:iii 欄目:大數據

今天小編給大家分享一下數據庫并發控制選擇樂觀鎖還是悲觀鎖的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

實際生產環境里邊,如果并發量不大,完全可以使用悲觀鎖定的方法,這種方法使用起來非常方便和簡單。但是如果系統的并發非常大的話,悲觀鎖定會帶來非常大的性能問題,所以就要選擇樂觀鎖定的方法

悲觀鎖假定其他用戶企圖訪問或者改變你正在訪問、更改的對象的概率是很高的,因此在悲觀鎖的環境中,在你開始改變此對象之前就將該對象鎖住,并且直到你提交了所作的更改之后才釋放鎖。悲觀的缺陷是不論是頁鎖還是行鎖,加鎖的時間可能會很長,這樣可能會長時間的限制其他用戶的訪問,也就是說悲觀鎖的并發訪問性不好。

樂觀鎖則認為其他用戶企圖改變你正在更改的對象的概率是很小的,因此樂觀鎖直到你準備提交所作的更改時才將對象鎖住,當你讀取以及改變該對象時并不加鎖。可見樂觀鎖加鎖的時間要比悲觀鎖短,樂觀鎖可以用較大的鎖粒度獲得較好的并發訪問性能。

但是如果第二個用戶恰好在第一個用戶提交更改之前讀取了該對象,那么當他完成了自己的更改進行提交時,數據庫就會發現該對象已經變化了,這樣,第二個用戶不得不重新讀取該對象并作出更改。這說明在樂觀鎖環境中,會增加并發用戶讀取對象的次數。以版本控制系統為例,來說說兩種最基本的并發性問題。

丟失更新:

小張想修改源代碼里面的a方法,正在她修改的同時,小李打開了這個文件,修改了b方法并且保存了文件,等小張修改完成后,保存文件,小李所做的修改就被覆蓋了。

不一致的讀:

小張想要知道包里面一共有多少個類,包分了a,b兩個子包。小張打開a包,看到了7個類。突然小張接到老婆打來的電話,在小張接電話的時候,小李往a包中加了2個類,b包中加了3個類(原先b包中是5個類)。

小張接完電話后再打開b包,看到了8個類,很自然得出結論:包中一共有15個類。

很遺憾,15個永遠不是正確的答案。在小李修改前,正確答案是12(7+5),修改后是17(9+8)。這兩個答案都是正確的,雖然有一個不是當前的。但15不對,因為小張讀取的數據是不一致的。

小結:不一致讀指你要讀取兩種數據,這兩種數據都是正確的,但是在同一時刻兩者并非都正確。

隔離和不可變:

在企業應用中,解決并發沖突的兩種常用手段是隔離和不可變。

只有當多個活動(進程或者線程)同時訪問同一數據時才會引發并發問題。一種很自然的思路就是同一時刻只允許一個活動訪問數據。如果小張打開了文件,就不允許其他人打開,或者其他人只能通過只讀的方式打開副本,就可以解決這個問題。

隔離能夠有效減少發生錯誤的可能。我們經常見到程序員陷入到并發問題的泥潭里,每一段代碼寫完都要考慮并發問題,這樣太累了。我們可以利用隔離技術創建出隔離區域,當程序進入隔離區域時不用關心并發問題。好的并發性設計就是創造這樣的一些隔離區域,并保證代碼盡可能的運行在其中。

另一種思路:只有當你需要修改共享的數據時才可能引發并發性問題,所以我們可以將要共享的數據制作為“不可變”的,以避免并發性問題。當然我們不可能將所有的數據都做成不可變的,但如果一些數據是不可變的,對它們進行并發操作時我們就可以放松自己的神經了。

樂觀并發控制、悲觀并發控制:

如果數據是可變的,并且無法隔離呢?這種情況下最常用的兩種控制就是樂觀并發控制和悲觀并發控制。

假設小張和小李想要同時修改同一個文件。如果使用樂觀鎖,倆人都能打開文件進行修改,如果小張先提交了內容,沒有問題,他所做的改變會保存到服務器上。但小李提交時就會遇到麻煩,版本控制服務器會檢測出兩種修改的沖突,小李的提交會被具體,并由小李決定該如何處理這種情況(對于絕大部分版本控制軟件來說,會讀取并標識出小張做的改變,然后由小李決定是否合并)。

如果使用的是悲觀鎖,小張先檢出(check out)文件,那么小李就無法再次檢出同一文件,直到小張提交了他的改變。

建議你將樂觀鎖想成一種檢測沖突的手段,而悲觀鎖是一種避免沖突的手段(嚴格來說,樂觀鎖其實不能稱之為“鎖”,但是這個名字已經流傳開了,那就繼續使用吧)。一些老的版本控制系統,比如VSS 6.0使用的是悲觀鎖的機制。而現代的版本控制系統一般兩種都支持,默認使用樂觀鎖。

兩種鎖各有優缺點。這段懶的翻譯了,很明顯看出,樂觀鎖可以提高并發訪問的效率,但是如果出現了沖突只能向上拋出,然后重來一遍;悲觀鎖可以避免沖突的發生,但是會降低效率。

選擇使用那一種鎖取決于訪問頻率和一旦產生沖突的嚴重性。如果系統被并發訪問的概率很低,或者沖突發生后的后果不太嚴重(所謂后果應該指被檢測到沖突的提交會失敗,必須重來一次),可以使用樂觀鎖,否則使用悲觀鎖。

我們可以使用兩種形式的并發控制策略:樂觀并發控制和悲觀并發控制。

假設martin和David同時都要編輯Customer文件。如果使用樂觀鎖策略,他們兩個人都能得到一份文件的Copy,并且可以自由編輯文件。假設David第一個完成了工作,那么他可以毫無困難地更新他的修改。但是,當Martin想要提交他的修改時,并發控制策略就會開始起作用。

源代碼控制系統會檢測到在Martin的修改與David的修改之間存在著沖突,因而拒絕Martin的提交,并由Martin負責指出怎樣處理這種情況。如果使用悲觀鎖策略,只要有人先取出文件,其他人就不能對該文件進行編輯。因此,假如是Martin先取了文件,那么David就只能在Martin完成任務并提交之后才能對該文件進行操作。

如果把樂觀鎖看作是關于沖突檢測的,那么悲觀鎖就是關于沖突避免的。在實際應用的源代碼控制系統中,這兩種策略都可以被使用,但是現在大多數源代碼開發者更傾向于使用樂觀鎖策略。

有一種很有道理的說法:樂觀鎖并不是真正的鎖定,但是這種叫法很方便并且廣泛流傳,以至于不容忽略。

這兩種策略各有優缺點。悲觀鎖的問題是減少了并發的程序。當Martin正對一個被他加鎖的文件進行編輯的時候,其它人只能等著。使用過悲觀的源代碼控制人都知道這是一種多么令人喪氣的事情。對于企業數據,情況經常會變得更加糟糕,只要有人在編輯,其他人就無法進行讀取,更加說進行編輯了。

樂觀鎖策略則允許人們更自由一些,因為只有在提交的時候才有可能遇到阻礙。該策略的問題在于當沖突的時候會發生什么樣的事情呢?事實上,David之后的所有人在提交的時候都必須讀取David修改過的那個版本,并指出怎樣合并自己和David的修改,然后再提交一個重新修改過的最新版本。

有了源代碼控制系統,這樣做并不會有什么麻煩。在許多場合下,源代碼控制系統確實能夠自動進行合并操作,甚至在無法自動合并的時候,也能讓使用都很容易看出不同文件版本之間的差別。但是,業務數據通常都是很難被自動合并的,所以經常只能扔掉原來的東西,然后從頭開始。

在樂觀鎖和悲觀鎖之間進行選擇的標準是:沖突的頻率與嚴重性。如果沖突很少,或者沖突的后果不會很嚴重,那么通常情況下應該選擇樂觀鎖,因為它能得到更好的并發性,而且更容易實現。但是,如果沖突的結果對于用戶來說痛苦的,那么就需要使用悲觀策略。

樂觀鎖的局限是:

只能在提交數據時才發現業務事務將要失敗,而且在某些情況下,發現失敗太遲的代價會很大。用戶可能花了一個小時的時間輸入一份租約的詳細信息,錯誤太多會讓用戶對系統失去信心。另一個方法是使用悲觀鎖,它可以盡早地發現錯誤,但理難以編程實現,而且會降低系統的靈活性。

注:以上是對并發控制中的樂觀鎖策略和悲觀鎖策略概念及解決思路的文字描述,下面我將對項目中具體怎么實現樂觀鎖策略及悲觀鎖策略進行描述。

樂觀鎖策略實現方法:

就是用C#中或SQL中的事務來實現數據操作不成功就回滾,個人感覺火車站賣票系統也是這樣操作的,我們看到顯示屏上有少量剩余票,但我們去買又打不出來。

悲觀鎖策略實現方法:

1、普通的aspx頁面,當用戶點提交后,直接將提交及相關按鈕的enabel改為false,直到提交事件完成后,再改回來。另外在數據層那一塊,每次提交數據更改時,都需要判斷數據以前的狀態是否改變,以防止有并發改變的情況出現。

2、jquery中,在jquery中,可以設置一個全局變量,提交時,先判斷全局變量狀態,如不允許提交則直接返回,如允許提交時,則先將全局變量置為“不允許提交”,后開始提交,提交完成后,在jquery的post方法的callback方法中,再將全局變量改為“允許提交”。

3、彈出式窗口修改頁面,則用模態方式彈出,如web頁面中,可用window.show ModalDialog()來實現模態方式打開修改頁面,來確保始終只有一個修改頁面被打開。這是從數據操作頁面處就悲觀鎖定了數據,而不是在數據庫里面悲觀鎖定。

以上就是“數據庫并發控制選擇樂觀鎖還是悲觀鎖”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

崇礼县| 尼勒克县| 苏尼特左旗| 出国| 台前县| 天全县| 黔西| 澄城县| 蒲城县| 黎平县| 石屏县| 泰和县| 陵水| 武隆县| 万荣县| 湟中县| 社旗县| 石屏县| 赣州市| 黔南| 武邑县| 滁州市| 天等县| 高台县| 阜南县| 邢台市| 调兵山市| 临桂县| 南涧| 榆中县| 柏乡县| 普陀区| 大厂| 大理市| 乐都县| 罗田县| 县级市| 博罗县| 广汉市| 永顺县| 沙田区|