為了得到最大的效能,一般資料庫都有併發機制,不過帶來的問題就是資料訪問的衝突。為了解決這個問題,大多數資料庫用的方法就是資料的鎖定。
考慮下面的情況。如果我們先查找到資料,然後更新資料。這樣會出現這樣的情況。a執行緒查詢的時候,b執行緒也在查詢,當a執行緒準備更新的時候,b執行緒先獲得 了更新鎖,將這些行鎖定了。a只能等待b更新完。當b執行緒更新完釋放鎖的時候,a獲得鎖,這時a會識別出欄位已經修改,所以會重新查詢資料,然後開始更 新。
這在資料庫中本來是沒什麼問題的。但應用程式中會出現乙個問題。假如有乙個修改商品資訊的頁面
a,開啟這個頁面,得到商品資料。有編號 ,名稱 ,**。
b,也開啟這個頁面,得到商品資料。有編號 ,名稱 ,**。
然後a修改商品的**,然後點儲存。
b修改商品的名稱,點儲存。
這裡有乙個問題是,當a儲存修改後的商品**時,他實際上儲存了原編號,原名稱,修改後**。
然後b再點儲存的時候,他實際上儲存了原編號,修改後的名稱,原**。
這樣,b的修改就將a的修改覆蓋了。導致a的修改無效。
那麼,怎麼解決這種問題呢。、?
這裡有兩種方法解決這個問題,也就是所謂的樂觀鎖和悲觀鎖。
悲觀鎖
悲觀鎖是這樣實現的。
當查詢到商品資訊,並試圖更新資料時,在查詢的語句後加上for update nowait
這表示當a從準備更新這個資料(查詢這個資料並顯示到頁面上)開始,這個資料就被鎖定了,當你更新完成,才釋放鎖。
當b也準備更新這個資料時,因為有for update nowait,查詢這個資料時並顯示到頁面上就會出錯。所以不會更新。
這樣就能保證每次只有乙個準備更新的連線。從而就保證了資料不會出現丟失更新
悲觀鎖假定其他使用者企圖訪問或者改變你正在訪問、更改的物件的概率是很高的,因此在悲觀鎖的環境中,在你開始改變此物件之前就將該物件鎖住,並且直 到你提交了所作的更改之後才釋放鎖。悲觀的缺陷是不論是頁鎖還是行鎖,加鎖的時間可能會很長,這樣可能會長時間的限制其他使用者的訪問,也就是說悲觀鎖的並 發訪問性不好。
也就是說,當我們找到需要更改的物件時,就把這些行鎖定,只能讓我修改。當我修改完成時,再釋放這個鎖,別人才能修改。這樣就能防止我找到需要更改的物件到我開始更新資料這段時間內,其他執行緒獲得鎖先更新資料的情況。
樂觀鎖
樂觀鎖是這樣實現的。
每次更新時都和舊版本的資料比較。具體如下:
a,開啟這個頁面,得到商品資料。有編號 ,名稱 ,**。
b,也開啟這個頁面,得到商品資料。有編號 ,名稱 ,**。
然後a修改商品的**,然後點儲存。這時更新語句是這樣的
set 編號 = 原編號 ,名稱 = 原名稱 ,** =新** where 編號 = 原編號 ,名稱 = 原名稱 ,** =原**
因為a更新時滿足where後條件,所以更新成功。
當b修改商品的名稱,點儲存。語句是這樣的
set 編號 = 原編號 ,名稱 = 新名稱 ,** =原** where 編號 = 原編號 ,名稱 = 原名稱 ,** =原**
此時**已經是新的**,所以**(新**) = 原** 條件不滿足,所以更新不成功。
這樣就避免了丟失更新。
每個資料都和舊資料比較,可能比較麻煩,可以專門建一列,用作版本列。
當更新一次時,版本列資料加1。這樣
然後a修改商品的**,然後點儲存。這時更新語句是這樣的
set 編號 = 原編號 ,名稱 = 原名稱 ,** =新** ,版本 = 版本 + 1 where 編號 = 原編號 ,版本 = 版本
因為a更新時滿足where後條件,所以更新成功。
當b修改商品的名稱,點儲存。語句是這樣的
set 編號 = 原編號 ,名稱 = 新名稱 ,** =原** ,版本 = 版本 + 1 where 編號 = 原編號 ,版本 = 版本
此時**已經是新的版本 ,所以版本 (新版本 ) = 原版本 條件不滿足,所以更新不成功。
這裡的版本號也可以採用時間戳型別,這樣可以順便看到該行最後更新的時間。
樂觀鎖則認為其他使用者企圖改變你正在更改的物件的概率是很小的,因此樂觀鎖直到你準備提交所作的更改時才將物件鎖住,當你讀取以及改變該物件時並不加鎖。 可見樂觀鎖加鎖的時間要比悲觀鎖短,樂觀鎖可以用較大的鎖粒度獲得較好的併發訪問效能。但是如果第二個使用者恰好在第乙個使用者提交更改之前讀取了該物件,那 麼當他完成了自己的更改進行提交時,資料庫就會發現該物件已經變化了,這樣,第二個使用者不得不重新讀取該物件並作出更改。這說明在樂觀鎖環境中,會增加並 發使用者讀取物件的次數。
資料庫中鎖型別的介紹:
有兩種基本的鎖型別,排它鎖(exclusive
locks,即x鎖)和共享鎖(share
locks,即s鎖)。當資料物件被加上排它鎖時,其他的事務不能對它讀取和修改。加了共享鎖的資料物件可以被其他事務讀取,但不能修改。數
據庫利用這兩種基本的鎖型別來對資料庫的事務進行併發控制。
其中dml鎖(data
locks,資料鎖),用於保護資料的完整性
dml鎖的目的在於保證併發情況下的資料完整性,dml鎖主要包括tm鎖和tx鎖,其中tm鎖稱為表級鎖,tx鎖稱為事務鎖或行級鎖。
在此分享的簡單的select
for
update應該屬於dml鎖中的tx鎖,屬於行級鎖!
Oracle建立悲觀鎖和樂觀鎖
為了得到最大的效能,一般資料庫都有併發機制,不過帶來的問題就是資料訪問的衝突。為了解決這個問題,大多數資料庫用的方法就是資料的鎖定。資料的鎖定分為兩種方法,第一種叫做悲觀鎖,第二種叫做樂觀鎖。什麼叫悲觀鎖呢,悲觀鎖顧名思義,就是對資料的衝突採取一種悲觀的態度,也就是說假設資料肯定會衝突,所以在資料開...
Oracle 悲觀鎖和樂觀鎖
悲觀鎖 如select for update 悲觀鎖大多數情況下依靠資料庫的鎖機制實現,以保證操作最大程度的獨占性。但隨之而來的就是資料庫效能的大量開銷,特別是對長事務而言,這樣 的開銷往往無法承受。樂觀鎖基於資料版本 version 機制實現 為資料增加乙個版本標識,在基於資料庫表的版本解決方案中...
悲觀鎖和樂觀鎖
1.悲觀鎖,正如其名,它指的是對資料被外界 包括本系統當前的其他事務,以及來自外部系統的事務處理 修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制 也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無...