當前位置:首頁 » 數據倉庫 » 怎麼在資料庫實現樂觀鎖
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

怎麼在資料庫實現樂觀鎖

發布時間: 2023-05-30 10:09:36

㈠ 操作oracle數據時報樂觀鎖異常

戶A打開應用的界面,看到資料庫的某條記錄

b.用戶B打開應用的界面,看到同樣一條記錄

c. 用戶A對記錄做了修改

d. 對於web應用而言[假設沒有應用comet類似技術],通常B不知道這個修改,這時B也對同樣這條記錄做修改,那B就有可能覆蓋A做的修改;

這個問題在資料庫中被稱為丟失更新問題

2.我自己對這個問題的理解過程是這樣的:

a. 不知道這個問題

我在做開發好長時間之後才意識到這個問題,意識到這個問題之後,我後來發現很長一段時間內都沒真正搞明白為什麼這是個問題-_- 而且我發現現在周圍的很多同事,尤其是新畢業的學生,其實也一直過了很長時間都沒明白這個問題,這說明吧不知道這個丟失更新問題是一個非常普遍的問題:)

b.用信號量以及操作之前再次驗證的方法解決

最開始的時候,測試發現了這樣一個問題,要求解決,我把操作系統的教科書搬來,對照著寫了一個信號量semaphore類[那時候還是jdk 1.4.2,jdk裡面沒有concurrent包],花了好長時間測試這個semaphore的實現是正確的[重復發明輪子的血淚史..],

然後用來控制這個操作,每次操作前獲取信號量,然後驗證,再做真正的資料庫操作。。。相當於在應用層每次都只做一件事。

c. 再次理解

再後來,我看了Tom的這本9i和10g的書,書中提到前面的丟失更新過程,大概有點明白為什麼這是個問題

.png

但是其實我有個疑問,對於資料庫中的記錄而言,A做的修改本來就有可能被B覆蓋的,為什麼這會是一個丟失更新問題呢? 正好項目裡面又出現了類似的情況,我仔細觀察了下,終於明白為什麼這是個問題,以及為什麼要使用對應的樂觀鎖悲觀鎖方案了。下面對此做詳細說明

3. 一個比較清楚的場景

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

假設當當網上用戶下單買了本書,這時資料庫中有條訂單號為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

如果當當的系統這樣實現,顯然不對了,肯定要挨罵了,明明已經取消了訂單,為什麼還會發貨呢?而且確實取消訂單的操作發生在發貨操作之前啊。 因為在這樣的實現下,後台管理人員無論怎麼做都有可能會出錯,因為他打開系統看到有效的訂單和他點發貨之間肯定有個時間差,在這個時間差的時候總是存在用戶取消訂單的可能。

4. 當時的詳細解決方法。幾年前當測試人員告訴我系統存在這個問題的時候,我的解決方法是這樣的, 首先,先把操作系統的教科書搬來,然後對照著了一個semaphore,然後反復測試各種情況證明寫的是正確的; 然後,

1. 獲取一個信號量,保證每次只能有一個線程進入下面的步驟

2. 檢查資料庫,看這條訂單是否狀態是有效的

a. 如果有效則繼續,進入發貨步驟 b) 如果無效則返回,釋放信號量,告訴用戶狀態已經發生改變

3. 發貨,釋放信號量

看到這里,也許很多人要罵我蠢了,直接把SQL語句改成下面這樣吧就可以了么? update order_table set status = 『已發貨』 where order_id = 001 and status = 『有效』 是的,的確是這樣。雖然我當時的項目的情況比和這個稍微復雜一點,涉及到多張表格,不能直接這么做,但當時的確不知道這個更新丟失問題,也沒想到合適的類似方式,於是就在應用層做了這么一個每次實際上只能有一個用戶在做真正的更新這樣一個方式來解決,這樣做的結果是,在應用層單獨做了類似這么一個鎖的機制。我記得當時的項目畢業答辯的時候,老師問我同步的這個問題不直接用資料庫的鎖的方案來解決?我當時胡亂回答了下,後來想起來,其實壓根沒理解老師的意思-_- 而且這樣做有一個問題,假設在特殊情況下,這條訂單被DBA直接修改了,沒有經過應用,那麼應用做這個操作也會是錯的,因為在2.a到3之前的這段時間,有可能正好是DBA直接修改的時候。那麼3做的操作也是不對的。 而且,現實情況是在後來的幾年開發過程中,我也的確在一些不同的項目代碼中看到,其他很多人也在使用類似的代碼解決測試人員告訴他們的這些同步問題-_-

5.正確而簡潔的解決方法

問題清楚了,也說明了我曾經使用的解決方案也是一個簡潔直接的解決方案,純粹是把簡單問題復雜化,下面說說實際有效的解決方案; 就這個丟失更新問題,可以通過資料庫的鎖來實現,基本兩種思路,一種是悲觀鎖,另外一種是樂觀鎖; 簡單的說就是一種假定這樣的問題是高概率的,最好一開始就鎖住,免得更新老是失敗;另外一種假定這樣的問題是小概率的,最後一步做更新的時候再鎖住,免得鎖住時間太長影響其他人做有關操作;

6. 樂觀鎖的方法

這里先說web開發中常用的樂觀鎖的方法:

1.很簡單,就是使用前面所說的這樣一條SQL,這其實是所謂使用」前鏡像」的方式來保證需要更新的數據是符合要求的,

update order_table set status = 『已發貨』 where order_id = 001 and status = 『有效』 Tom的書上舉的例子是對所有列做更新,所以他的SQL大致如下 Update table set col1 = newcol1value, col2 = newcol2value…. where col1 = oldcol1value and col2 = oldcol2value…. 這個我覺得需要根據應用具體分析,如果需要判斷所有的值,那就判斷所有的值,如果只關心其中一個或部分值,那隻需要取相關的值就好了,就比如這里的訂單的狀態

2.使用版本列[比如時間戳

這個方法比較簡單,也最常用,就是在資料庫表格中加一列last_modified_date,就是最後更新的時間,每次更新的時候都將這列設成systimestamp,當前系統時間;

然後每次更新的時候,就改成這樣 Update table set col = newvalue where id = ** and last_modified_date = old last_modified_date 這樣,就可以檢驗出資料庫的值是否在上次查看和這次更新的時候發生了變化,如果發生了變化,那麼last_modified_date就變化了,以後的更新就會返回更新了0行,系統就可以通知用戶數據發生了變化,然後選擇刷新數據或者其他流程。

至於這個last_modified_date的維護,可以選擇讓應用每次都維護這個值,或者是使用存儲過程來包裝更新的操作,或者是使用觸發器來更新相關的值。幾種方法各有利弊,比如應用維護需要保證每段相關代碼都正確的維護了這個值;存儲過程有一定的開銷,通常很多開發對寫存儲過程可能也不熟練;觸發器是簡單的實現,但是也是有開銷的。具體使用哪種方法需要根據實際情況具體取捨。

3.使用校驗或Hash值

這種方法和前面的方法類似,無非是根據其他有實際意義的列來計算出一個虛擬的列,我個人覺得TOM在介紹這個純粹是介紹了一種」奇技淫巧」,反正我是在實際過程中不知道哪裡會需要這樣的解決方案,或許也是因為我知道的太少了吧:)

4.使用Oracle 10g的ORA_ROWSCN

這個就是利用10g的一個ora_rowscn特性,可以對每行做精確追蹤,不過這個要求在create table的時候就指定相關參數,表格如果創建了以後就不能用alter table來修改了,因為這依賴於物理的實際存儲。 同樣,我覺得這也可以歸為」奇技淫巧」一類; 具體如果有興趣了解詳情的話,可以參考Tom的書

我們一直都在努力堅持原創.......請不要一聲不吭,就悄悄拿走。

我原創,你原創,我們的內容世界才會更加精彩!

【所有原創內容版權均屬TechTarget,歡迎大家轉發分享。但未經授權,嚴禁任何媒體(平面媒體、網路媒體、自媒體等)以及微信公眾號復制、轉載、摘編或以其他方式進行使用。】

微信公眾號

TechTarget

官方微博

TechTarget中國

相關資源:oracle樂觀鎖和悲觀鎖詳細教程_oracle的樂觀鎖-Oracle文檔類資源...
點擊閱讀全文
打開CSDN,閱讀體驗更佳

Oracle資料庫悲觀鎖與樂觀鎖_diweikang的博客
注:對於悲觀鎖是針對並發的可能性比較大,而一般在我們的應用中用樂觀鎖足以。 Oracle的悲觀鎖需要利用一條現有的連接,分成兩種方式,從SQL語句的區別來看,就是一種是for update,一種是for update nowait的形式。 1. 執行select xxx ...
ORACLE悲觀鎖和樂觀鎖_hongwei3344661的博客
1、無論是選擇悲觀鎖策略,還是樂觀鎖策略。如果一個對象被上了鎖,那麼該對象都會受這個鎖的控制和影響。 2、選擇悲觀鎖策略,還是樂觀鎖策略,這主要是由應用和業務需求來確定的。如果你的應用和業務經常會出現從我看到要修改的記錄的...
oracle 樂觀鎖和悲觀鎖詳細教程
詳細介紹了Oracle中樂觀鎖、悲觀鎖的原理及應用,並有實例
基於ORACLE的樂觀鎖實現原理
2019獨角獸企業重金招聘Python工程師標准>>> ...
繼續訪問
Oracle之悲觀鎖和樂觀鎖_hys21的博客
根據保護的對象不同,Oracle資料庫鎖可以分為以下幾大類:DML鎖(data locks,數據鎖),用於實現並發存取並保護數據的完整性;DDL鎖(dictionary locks,字典鎖),用於保護資料庫對象的結構,如表、索引等的結構定義;內部鎖和閂(internal locks ...
oracle樂觀鎖和悲觀鎖詳細教程_oracle的樂觀鎖-Oracle文檔類資源...
內部包含oracle網路網盤下載鏈接以及密碼。 oci.dll 12版本全部 資源是從Oracle官方網站下載,已測試可用 【白雪紅葉】JAVA學習技術棧梳理思維導圖.xmind 樂觀鎖行級鎖 分布式鎖 分區排隊 一致性 一致性演算法 paxos zab nwr raft gossip ...
Oracle創建悲觀鎖和樂觀鎖
為了得到最大的性能,一般資料庫都有並發機制,不過帶來的問題就是數據訪問的沖突。為了解決這個問題,大多數資料庫用的方法就是數據的鎖定。 考慮下面的情況。如果我們先查詢到數據,然後更新數據。這樣會出現這樣的情況。A線程查詢的時候,B線程也在查詢,當A線程准備更新的時候,B線程先獲得 了更新鎖,將這些行鎖定了。A只能等待B更新完。當B線程更新完釋放鎖的時候,A獲得鎖,這時A會識別出欄位已經
繼續訪問
Oracle並發控制中的樂觀鎖
資料庫的管理員要分散他們的資料庫,以便處理基於Web,B2B,電子商務的訪問,快速的硬碟讀寫以及更多的資源或許只能解決一部分問題。疲乏的鎖機制甚至會削弱擁有很好資源的應用性能。樂觀鎖可以大大改善具有較多事務處理的資料庫載入性能,比如基於web的客戶端訪問。 悲觀鎖引發的問題: 大多數Oracle開發者已經非常熟悉悲觀鎖,即在對數據進行更新之前給數據加鎖。使用熟悉的SELECT...FOR UP
繼續訪問
oracle樂觀鎖悲觀鎖學習筆記(更新中)_Evaron.Z的博客
首先解釋下樂觀鎖和悲觀鎖的含義 樂觀鎖:樂觀鎖就是認為數據一般情況下不會造成沖突,所以在數據進行提交更新的時候,才會正式對數據的沖突與否進行檢測,如果發現沖突了,則返回錯誤的信息。 悲觀鎖:悲觀鎖就是對數據的沖突採取一種悲觀的...
【Oracle】樂觀鎖和悲觀鎖_◣NSD◥的博客_oracle悲觀鎖...
樂觀鎖對應於生活中樂觀的人總是想著事情往好的方向發展,悲觀鎖對應於生活中悲觀的人總是想著事情往壞的方向發展。這兩種人各有優缺點,不能不以場景而定說一種人好於另外一種人。 悲觀鎖 ...
Oracle樂觀鎖悲觀鎖
1.樂觀鎖 當處理對象狀態時為了防止沖突 例:一個下訂單的狀態status a.更新status為1購買,b取得status為1,這時a要退貨把status改為2. 這時如果b還按1的狀態去處理,發貨了。就出錯了。 正確的做法為: 當b發貨時,為了處理並發臟讀,需要先根據原status狀態去更新status為3訂單處理中 int res = update...
繼續訪問
【轉】 Oracle中樂觀鎖定的四種實現方式
<br />Oracle中樂觀鎖定的四種實現方式<br /> <br />轉自 http://www.blogjava.net/lihao336/archive/2009/09/04/293934.html<br /> 更新前在應用中存儲所要操作行的「前映像」,更新時使用存儲的舊記錄來判斷當前值是否已經改變; 使用一個特殊的列,這個列由一個資料庫觸發器或應用程序代碼維護,可以告訴我們記錄的 「版本」; 使用一個校驗和或散列值,這是使用原來的數據計算得出的; 使用新增的 Oracle 10g 特性 ORA_R
繼續訪問
oracle的悲觀鎖和樂觀鎖
目錄 1 悲觀鎖 1.1 單表 for update 1.2 關聯表for update 1.3 解除for update 鎖的佔用 1.4 悲觀鎖缺點 2 樂觀鎖 2.1 比對法 2.2 版本戳 2.3 timestamp型 2.4 例子Demo 問select *from person for update或update perso...
繼續訪問
Oracle的悲觀鎖和樂觀鎖
為了得到最大的性能,一般資料庫都有並發機制,不過帶來的問題就是數據訪問的沖突。為了解決這個問題,大多數資料庫用的方法就是數據的鎖定。 數據的鎖定分為兩種方法,第一種叫做悲觀鎖,第二種叫做樂觀鎖。什麼叫悲觀鎖呢,悲觀鎖顧名思義,...
繼續訪問
oracle鎖機制之悲觀鎖與樂觀鎖以及for update用法
目錄 1 悲觀鎖 1.1 單表 for update 1.2關聯表for update 1.3 悲觀鎖缺點 2樂觀鎖 2.1 比對法 2.2版本戳 2.3timestamp型 2.4 例子Demo 1 悲觀鎖 所謂的悲觀鎖:顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次拿數據的時候都會上鎖。這樣別人拿數據的時候就要等待直到鎖的釋放。 資料庫行級...
繼續訪問
oracle的樂觀鎖和悲觀鎖
一、問題引出 ① 假設當當網上用戶下單買了本書,這時資料庫中有條訂單號為001的訂單,其中有個status欄位是』有效』,表示該訂單是有效的; ② 後台管理人員查詢到這條001的訂單,並且看到狀態是有效的; ③ 用戶發現下單的時候下錯了,於是撤銷訂單,假設運行這樣一條SQL: update order_table set status = 『取消』 whe
繼續訪問
Oracle鎖定:悲觀與樂觀鎖詳解
Oracle資料庫悲觀鎖與樂觀鎖是本文我們主要要介紹的內容。有時候為了得到最大的性能,一般資料庫都有並發機制,不過帶來的問題就是數據訪問的沖突。為了解決這個問題,大多數資料庫用的方法就是數據的鎖定…… 以下是代碼片段: select*fromtestwhereid=10也就是沒有for update這種鎖定數據的語句的話,就不會造成阻塞了。另外一種情況,就是當資料庫數據被鎖定的時候,也
繼續訪問
樂觀鎖與悲觀鎖——解決並發問題
引言 為什麼需要鎖(並發控制)? 在多用戶環境中,在同一時間可能會有多個用戶更新相同的記錄,這會產生沖突。這就是著名的並發性問題。 典型的沖突有: 丟失更新:一個事務的更新覆蓋了其它事務的更新結果,就是所謂的更新丟失。例如:用戶A把值從6改為2,用戶B把值從2改為6,則用戶A丟失了他的更新。 臟讀:當一個事務讀取其它完成一半事務的記錄時,就會發生臟讀取。例如:用戶A,B看到的...
繼續訪問
樂觀鎖和悲觀鎖策略的區別與實現
樂觀鎖和悲觀鎖策略的區別與實現 1、無論是選擇悲觀鎖策略,還是樂觀鎖策略。如果一個對象被上了鎖,那麼該對象都會受這個鎖的控制和影響。如果這個鎖是個排它鎖,那麼其它會話都不...
繼續訪問
oracle的共享鎖不起作用,ORACLE中的樂觀鎖、悲觀鎖、共享鎖、排他鎖
一、引入在資料庫操作中,如果不同的用戶或者事務並發地訪問同一數據,可能就會破壞數據到完整性,這時候我們就可以用鎖來保證數據的一致性。二、概念1. 悲觀鎖就是很悲觀地任認為我每次要修改數據時,其他的操作總會來改變我要修改的數據,於是就將其加鎖。這樣一來,其他人只能等待我先放開鎖後才能操作數據。請看以下的示例。造數:CREATE TABLE test_yyw(id NUMBER(4),name VAR...
繼續訪問
oracle 鎖定 問題
鎖(lock)機制用於管理對共享資源的並發訪問。 資料庫中使用鎖是為了支持對共享資源進行並發訪問,與此同時還能提供數據完整性和一致性。 在Oracle中,你會了解到: ? 事務是每個資料庫的核心,它們是「好東西」。 ? 應該延遲到適當的時刻才提交。不要太快提交,以避免對系統帶來壓力。這是因為,如果事務很長或很大,一般不會對系統有壓力。相應的原則是:在必要時才提交,但是此前不要提
繼續訪問
最新發布 oracle資料庫加悲觀鎖,Oracle 悲觀鎖跟樂觀鎖
EMPNO ENAME SAL7782 CLARK 2450.007839 KING 5000.007934 MILLER 1300.00在SQLplus中模擬應用可能執行的綁定調用,可以利用下面命名:SQL> variable empno numberSQL> variable ename varchar2(20)SQL> var...
繼續訪問
Oracle 樂觀鎖、悲觀鎖
oracle有悲觀鎖也有樂觀鎖。 悲觀鎖比較安全一些,可以防止丟失更新,但是就是互相等待,影響效率。 一般會用樂觀鎖,即開始操作時,樂觀的認為數據不會被其他人更改,直到提交時才加鎖檢查。比如在操作的表上加一列,保存個時間戳,提交時檢查是不是最新的。不過樂觀鎖失敗的可能性比較大。 樂觀鎖,大多是基於數據版本( Version )記錄機制實現。
繼續訪問
oracle樂觀鎖實例
oracle 悲觀鎖和樂觀鎖
寫評論

評論

收藏

點贊



分享
前往CSDN APP閱讀全文
閱讀體驗更佳

CSDN

成就一億技術人

前往

㈡ 樂觀鎖的實現

Hibernate 在其數據訪問引擎中內置了樂觀鎖實寬粗現。如果不用考慮外部系統對資料庫的更新操作,利用 Hibernate 提供的透明化樂觀鎖實現,將大大提升我們的生產力。
Hibernate 中可以通過 class 描述符的 optimistic-lock 屬性結合 version
描述符指定。
現在,我們為之前示例中的 TUser 加上樂觀鎖機制。 首慎尺鎮先為 TUser 的 class 描述符添加 optimistic-lock 屬性:
<hibernate-mapping>
<class
name="org.hibernate.sample.TUser"
table="t_user"
dynamic-update="true"
dynamic-insert="true"
optimistic-lock="version"
>
……
</class>
</hibernate-mapping>
optimistic-lock 屬性有如下可選取值:
&Oslash; none
無樂觀鎖
&Oslash; version
通過版本機制實現樂觀鎖
&Oslash; dirty
通過檢查發生變動過的屬性實現樂觀鎖
&Oslash; all
通過檢查所有屬性實現樂觀鎖
其中通過 version 實現的樂觀鎖機制是 Hibernate 官方推薦的樂觀鎖實現,同時也
是 Hibernate 中,目前唯一在數據對象脫離 Session 發生修改的情況下依然有效的鎖機
制。因此,一般情況下,我們困攜都選擇 version 方式作為 Hibernate 樂觀鎖實現機制。 添加一個 Version 屬性描述符
<hibernate-mapping>
<class
name="org.hibernate.sample.TUser"
table="t_user"
dynamic-update="true"
dynamic-insert="true"
optimistic-lock="version"
>
<id
name="id"
column="id"
type="java.lang.Integer"
>
<generator class="native">
</generator>
</id>
<version
column="version"
name="version"
type="java.lang.Integer"
/>
……
</class>
</hibernate-mapping>
注意 version 節點必須出現在 ID 節點之後。
這里我們聲明了一個 version 屬性,用於存放用戶的版本信息,保存在 TUser 表的version 欄位中。
此時如果我們嘗試編寫一段代碼,更新 TUser 表中記錄數據,如:
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Erica"));
List userList = criteria.list();
TUser user =(TUser)userList.get(0);
Transaction tx = session.beginTransaction();
user.setUserType(1); // 更新 UserType 欄位
tx.commit();
每次對 TUser 進行更新的時候,我們可以發現,資料庫中的 version 都在遞增。而如果我們嘗試在 tx.commit 之前,啟動另外一個 Session ,對名為 Erica 的用戶進行操作,以模擬並發更新時的情形:
Session session= getSession();
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Erica"));
Session session2 = getSession();
Criteria criteria2 = session2.createCriteria(TUser.class);
criteria2.add(Expression.eq("name","Erica"));
List userList = criteria.list();
List userList2 = criteria2.list();TUser user =(TUser)userList.get(0);
TUser user2 =(TUser)userList2.get(0);
Transaction tx = session.beginTransaction();
Transaction tx2 = session2.beginTransaction();
user2.setUserType(99);
tx2.commit();
user.setUserType(1);
tx.commit();
執行以上代碼,代碼將在 tx.commit() 處拋出 StaleObjectStateException 異常,並指出版本檢查失敗,當前事務正在試圖提交一個過期數據。通過捕捉這個異常,我們就可以在樂觀鎖校驗失敗時進行相應處理。

㈢ mysql如何實現樂觀鎖

樂觀鎖與悲觀鎖不同的是,它是一種殲族邏輯上的鎖,而不需要資料庫提供鎖機制來氏肆弊支持
當數據很重要,回滾或重試一次需要很大的開銷時,需要保證操作的ACID性質,此時應該採用悲觀鎖
而當數據對即時的一致性要求不高,重試一次不太影響整體性能時,可以採用樂觀鎖來保證最終一致性,同時有利於提高並發性
通常,樂觀鎖採用版本號/時間戳的形式實現:給數據額外增加一個版本號欄位進行控制;更新時,若提交的數據所帶的版本號與當前記錄的版本號一致,則允許變更執行並更新版本號;若不一致,則意味著產生沖突,根據業務需求直接丟棄並返回失敗,或者嘗試合並
在MySQL的實踐中,常見的一種使用樂觀鎖的方法,是在需要使用樂觀鎖的表中,新增一個version欄位
例如:
create table proct_amount (
id int not null primary key auto_increment,
proct_name varchar(64) not null,
selling_amount int not null,
storing_amount int not null,
version int not null
);
當需要更新銷售中的商品數量(selling_amount)時,使用如下的SQL語句:
update proct_amount set selling_amount = #{selling_amount}, version = #{new_version} where id=#{id} and version = #{old_version};
若該語句返回1,則表示更新成功;若返回0,則表示前後的version不一致,產生沖突,更新失敗
對於更新倉庫中的商品數據(storing_amount)時,也是同理
不過,這樣為每行記錄都統一設置一個version欄位的樂觀鎖方式,存在一個問題:上例中,如果同時需要單獨對selling_amount及storing_amount進行update(兩雹擾條SQL語句分別單獨執行),那麼後執行的一條會因為先執行的一條更新了version欄位而失敗,而這種失敗顯然是沒有必要的,白白浪費了開銷
一種比較好的方式是為每個需要樂觀鎖的欄位單獨設置版本號,例如對上例的改造:
create table proct_amount (
id int not null primary key auto_increment,
proct_name varchar(64) not null,
selling_amount int not null,
selling_version int not null,
storing_amount int not null,
storing_version int not null
);
selling_amount和storing_amount分別擁有自己的樂觀鎖版本號(selling_version和storing_version),更新時分別只關注自己的版本號,這樣就不會因為版本號被其它欄位修改而失敗,提高了並發性

㈣ 資料庫死鎖處理方法

mysql數據謹銀庫死鎖解決方法如下:

1、對於按鈕等控制項,點擊後使其立刻失效,不讓用戶重復點擊,避免對同時對同一條記錄操作。

2、使用樂觀鎖進行控制。樂觀鎖大多是基於數祥核宴據版本(Version)記錄機制實現。即為數據增加一個版本標識,在基於資料庫表的版本解決方案中,一般是 通過為資料庫表增加一個「version」欄位來實現。讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交數據的版本數據與數 據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於資料庫表當前版本號,則予以更新,否則認為是過期數據。樂觀鎖機制避免了長事務中的數據 庫加鎖開銷(用戶A和用戶B操作過程中,都沒有對資料庫數據加鎖),大大提升了大並發量下的系統整體性能表現。Hibernate 在其數據訪問引擎中內置了樂觀鎖氏帶實現。需要注意的是,由於樂觀鎖機制是在系統中實現,來自外部系統的用戶更新操作不受系統的控制,因此可能會造 成臟數據被更新到資料庫中。

㈤ 如何實現樂觀鎖,如何避免aba問題

悲觀鎖資料庫面鎖住 類似for update查詢
樂觀鎖資料庫端鎖住
程序控制
說Mybatis我知道
樂觀鎖般
比資料庫慧者宏條記錄
給加版本號

同2查詢數據要修改
第先查事走
第二查給改
候前冊看
第查數據版嫌謹本號比1
第二查1 改數據版本號變2
候第繼續修改數據
版本號1 比2低
候告訴數據期
樂觀鎖概意思
種思路

㈥ mysql中的樂觀鎖和悲觀鎖怎麼用

關於mysql中的樂觀鎖和悲觀鎖面試的時候被問到的概率還是比較大的。
mysql的悲觀鎖:
其實理解起來非常簡單,當數據被外界修改持保守態度,包括自身系統當前的其他事務,以及來自外部系統的事務處理,因此,在整個數據處理過程中,將數據處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制,但是也只有資料庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在自身系統中實現了加鎖機制,也無法保證外部系統不會修改數據。
來點實際的,當我們使用悲觀鎖的時候我們首先必須關閉mysql資料庫的自動提交屬性,因為MySQL默認使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。

關閉命令為:set autocommit=0;
悲觀鎖可以使用select…for update實現,在執行的時候會鎖定數據,雖然會鎖定數據,但是不影響其他事務的普通查詢使用。此處說普通查詢就是平時我們用的:select * from table 語句。在我們使用悲觀鎖的時候事務中的語句例如:
//開始事務
begin;/begin work;/start transaction; (三選一)
//查詢信息
select * from order where id=1 for update;
//修改信息
update order set name='names';
//提交事務
commit;/commit work;(二選一)
此處的查詢語句for update關鍵字,在事務中只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一條數據時會等待其它事務結束後才執行,一般的SELECT查詢則不受影響。

執行事務時關鍵字select…for update會鎖定數據,防止其他事務更改數據。但是鎖定數據也是有規則的。
查詢條件與鎖定范圍:
1、具體的主鍵值為查詢條件
比如查詢條件為主鍵ID=1等等,如果此條數據存在,則鎖定當前行數據,如果不存在,則不鎖定。
2、不具體的主鍵值為查詢條件
比如查詢條件為主鍵ID>1等等,此時會鎖定整張數據表。
3、查詢條件中無主鍵
會鎖定整張數據表。
4、如果查詢條件中使用了索引為查詢條件
明確指定索引並且查到,則鎖定整條數據。如果找不到指定索引數據,則不加鎖。
悲觀鎖的確保了數據的安全性,在數據被操作的時候鎖定數據不被訪問,但是這樣會帶來很大的性能問題。因此悲觀鎖在實際開發中使用是相對比較少的。

mysql的樂觀鎖:
相對悲觀鎖而言,樂觀鎖假設數據一般情況下不會造成沖突,所以在數據進行提交更新的時候,才會對數據的沖突與否進行檢測,如果發現沖突,則讓返回用戶錯誤的信息,讓用戶決定如何去做。
一般來說,實現樂觀鎖的方法是在數據表中增加一個version欄位,每當數據更新的時候這個欄位執行加1操作。這樣當數據更改的時候,另外一個事務訪問此條數據進行更改的話就會操作失敗,從而避免了並發操作錯誤。當然,還可以將version欄位改為時間戳,不過原理都是一樣的。
例如有表student,欄位:
id,name,version
1 a 1
當事務一進行更新操作:update student set name='ygz' where id = #{id} and version = #{version};
此時操作完後數據會變為id = 1,name = ygz,version = 2,當另外一個事務二同樣執行更新操作的時候,卻發現version != 1,此時事務二就會操作失敗,從而保證了數據的正確性。
悲觀鎖和樂觀鎖都是要根據具體業務來選擇使用,本文僅作簡單介紹。

㈦ java多用戶同時修改一條數據時樂觀鎖怎麼用的

你說的這個version是mysql底層的鎖機制提供的,並不是java提供的。
使用數據版本(Version)記錄機制實現,這是mysql樂觀鎖最常用的一種實現方式。所謂的數據版本就是給數據增加一個版本標識,一般是通過為資料庫表清念增加一個數字類型的 「version」 欄位來實現。當讀取數據時,將version欄位的值一同讀出,數據每更新一次,對此version值加1。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本信息與第一次取出來散正州的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否沖蔽則認為是過期數據,版本號重新讀取再做更新。

㈧ 什麼是樂觀鎖

hibernate中兩種鎖機制: 悲觀鎖,樂觀鎖.
悲觀鎖:採用資料庫本身的鎖機制,for update或no wait
優點:處理並發徹底,並發處理比較好
缺點:當一個用戶鎖定記錄的時候,其它用戶都不能使用了,容易造成長時間的等待.

樂觀鎖:是Hibernate自己實現的,採用版本控制的方式實現處理並發.
1.添加version元素
2.聲明使用版本控制的方式實現樂觀鎖optimistic-lock="version"
<hibernate-mapping>
<class name="..." table="..." catalog="..." optimistic-lock="version"></class></hibernate-mapping>