java oracle 乐观锁,oracle为什么默认乐观锁
本帖最后由 bfc99 于 2015-7-6 11:08 編輯
1、無論是選擇悲觀鎖策略,還是樂觀鎖策略。如果一個對象被上了鎖,那么該對象都會受這個鎖的控制和影響。如果這個鎖是個排它鎖,那么其它會話都不能修改它。
2、選擇悲觀鎖策略,還是樂觀鎖策略,這主要是由應用和業務需求來確定的。如果你的應用和業務經常會出現從我看到要修改的記錄的值,到我修改完成該記錄這個時間段內,該記錄有較大概率被其它會話所修改。換句話說就是,在我真正去做出修改時,這個記錄的值很可能已經與我當初看到的不同了。那么這時,采取悲觀鎖策略,也許是更好的。而采取悲觀鎖策略的一個典型操作就是 select ... for undate。通過這種操作,使得從我一開始查看該記錄起,這條記錄就被上了排它鎖,不允許其它會話再對該記錄有任何修改。
相對的,如果你的業務和應用基本上很少出現這種情景,那么選擇樂觀鎖策略也許就會更好。
3、這兩種策略的核心其實就是持有鎖的時間的起止點不同,悲觀鎖是從讀取記錄的那一刻就開始了,而樂觀鎖只從UPDATE那一刻開始;結束的點兩者是一樣的,都是發出commit或rollback命令。所以,悲觀鎖策略會使鎖的持續時間更長,而樂觀鎖的持續時間則較短。其影響就是并發。悲觀鎖的并發性低于樂觀鎖。
4、無論是采用哪種策略,都要保證數據的完整性。所以,在采用樂觀鎖策略時,是有可能出現數據的不完整。舉例來說:儲戶甲的存款余額100元,假設在幾乎相同的時刻,發生了兩筆業務,業務1為其存入了50元,另一個業務是其網上購物消費了30元。顯然,這兩個操作結束后,甲的存款余額應為120元(100+50-30)。但我們設想一下在數據庫層面,可能出現這種情況,當其在銀行柜臺存入50元時,銀行操作員收到了甲存入的50元現金,并通過 select 語句看到甲的當前余額為100元(其發出的指令是下面的語句:
select 余額
from 存款余額表
where 儲戶帳號=儲戶甲的銀行帳號;)
,接著,發出指令
update 存款余額表
set 余額=150
where 儲戶帳號=儲戶甲的銀行帳號;
但就在其看到甲的余額為100元,到其修改甲的余額為150這期間,甲在網上的消費行為導致交易系統已經將甲的余額變成了70元(100-30)并提交了。當銀行員工發出的指令也被提交后,甲的余額變成了150元,相當于甲網上消費的行為沒有產生任何扣款。這顯然是不正確的,更是要避免出現的。
如果這套系統采用的是悲觀鎖策略,那么在從銀行員工查看甲當前余額的那一個時刻起(這時查詢的指令就會是:
select 余額
from 存款余額表
where 儲戶帳號=儲戶甲的銀行帳號 for update;)
該記錄就已經被鎖定了,這時甲網上消費的行為導致的交易系統從甲的帳戶中扣減的操作就會處于等待狀態。直至銀行員工提交了相關指令,交易系統才能去扣減甲的錢款。這樣,就可以確保甲的帳戶余額是正確的。
悲觀鎖的策略顯然可以保證業務的正確性和完整性。但再設想一下,如果甲在存款時,銀行員工內急,或者儲戶甲說等一等,我要考慮一下是否再多存一些。那么,銀行員工的操作就不會提交,這時網上交易系統對甲帳戶的扣款操作就會一直處于等待狀態,或者在等待一定時間后,返回一個扣款失敗的提示。這對于系統的效率和客戶來說,都不是一個好的體驗。
5、因為考慮到樂觀鎖策略可以產生的這種問題,所以,我們在設計應用時,可以采取一些其它方法來避免上述情況的發生。其思想就是在真正提交時,確認要修改的數據沒有變化過。主要的方法如下:
(1)、更新時帶入原始的數據。
update 存款余額表
set 余額=150
where 儲戶帳號=儲戶甲的銀行帳號 and 余額=100;
(2)、在記錄上增加修改的時間戳(也可利用ora_rowscn偽列)。即在事務開始時,獲取該記錄的時間戳,修改時,校驗該時間戳,若一致則修改。
6、其實,我上面舉的這個例子,如果在業務設計時,選擇更新指令為
update 存款余額表
set 余額=余額+50
where 儲戶帳號=儲戶甲的銀行帳號;
那么,即使是在樂觀鎖策略的情況下,依然可以保證數據的正確性和完整性。
總結
以上是生活随笔為你收集整理的java oracle 乐观锁,oracle为什么默认乐观锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle 如何表分析,ORACLE的
- 下一篇: oracle千万级分页优化,oracle