當前位置:成語大全網 - 新華字典 - 操作oracle數據時報樂觀鎖異常

操作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的書,書中提到前面的丟失更新過程,大概有點明白為什麽這是個問題

8a7315603d51c12ef97a82729cdc4677.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 />轉自 /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

成就壹億技術人

前往