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