數據庫鎖總結

文章來源:http://www.cnblogs.com/ismallboy/p/5574006.html

  數據庫鎖出現的原因是爲了處理併發問題,因爲數據庫是一個多用戶共享的資源,當出現併發的時候,就會導致出現各種各樣奇怪的問題,就像程序代碼一樣,出現多線程併發的時候,如果不做特殊控制的話,就會出現意外的事情,比如“髒“數據、修改丟失等問題。所以數據庫併發需要使用事務來控制,事務併發問題需要數據庫鎖來控制,所以數據庫鎖是跟併發控制和事務聯繫在一起的。

  平時會經常看到或者聽到數據庫鎖有“共享鎖”,“排它鎖”,“互斥鎖”,“寫鎖”,“讀鎖”,“悲觀鎖”,“樂觀鎖”,“行級鎖”,“表級鎖”,“頁級鎖”等,同時我們還會常看到“丟失修改“,”不可重複讀“,”讀髒數據“這三個術語,他們究竟是什麼關係以及怎麼理解呢,下面就來介紹一下他們。

  先說事務的特性,要想成爲事務,必須滿足:ACID(原子性,一致性,隔離性,持久性)四特性,事務是恢復和併發控制的基本單位。原子性指的是事務是數據庫的邏輯工作單位,事務中操作要麼都做,要麼都不做;一致性指的是事務的執行結果必須是使數據庫從一個一致性狀態變大另一個一致性狀態,一致性和原子性是密切相關的;隔離性指的是一個事務執行不能被其他事務干擾;持久性指的是一個事務一旦提交,他對數據庫中數據的改變就是永久性的。

  先說悲觀鎖和樂觀鎖吧。併發控制一般採用三種方法,分別是樂觀鎖和悲觀鎖以及時間戳。樂觀鎖認爲一個用戶讀數據的時候,別人不會去寫自己所讀的數據;悲觀鎖就剛好相反,覺得自己讀數據庫的時候,別人可能剛好在寫自己剛讀的數據,其實就是持一種比較保守的態度;時間戳就是不加鎖,通過時間戳來控制併發出現的問題。悲觀鎖就是在讀取數據的時候,爲了不讓別人修改自己讀取的數據,就會先對自己讀取的數據加鎖,只有自己把數據讀完了,才允許別人修改那部分數據,或者反過來說,就是自己修改某條數據的時候,不允許別人讀取該數據,只有等自己的整個事務提交了,才釋放自己加上的鎖,才允許其他用戶訪問那部分數據。樂觀鎖就比較簡單了,就是不做控制,這只是一部分人對於併發所持有的一種態度而已。時間戳就是在數據庫表中單獨加一列時間戳,比如“TimeStamp”,每次讀出來的時候,把該字段也讀出來,當寫回去的時候,把該字段加1,提交之前 ,跟數據庫的該字段比較一次,如果比數據庫的值大的話,就允許保存,否則不允許保存,這種處理方法雖然不使用數據庫系統提供的鎖機制,但是這種方法可以大大提高數據庫處理的併發量,因爲這種方法可以避免了長事務中的數據庫加鎖開銷(操作員A 和操作員B操作過程中,都沒有對數據庫數據加鎖),大大提升了大併發量下的系 統整體性能表現。 需要注意的是,樂觀鎖機制往往基於系統中的數據存儲邏輯,因此也具備一定的局 限性,如在上例中,由於樂觀鎖機制是在我們的系統中實現,來自外部系統的用戶 餘額更新操作不受我們系統的控制,因此可能會造成髒數據被更新到數據庫中。在 系統設計階段,我們應該充分考慮到這些情況出現的可能性,並進行相應調整(如 將樂觀鎖策略在數據庫存儲過程中實現,對外只開放基於此存儲過程的數據更新途 徑,而不是將數據庫表直接對外公開)。以上悲觀鎖所說的加“鎖”,其實分爲幾種鎖,分別是:排它鎖和共享鎖,其中排它鎖又稱爲寫鎖,共享鎖又稱爲讀鎖。(ps.可以參考此文 “http://blog.sina.com.cn/s/blog_548bd2090100ir7k.html”)

  共享鎖和排它鎖是具體的鎖,是數據庫機制上的鎖,存在以下關係:

  

      (x表示是排它鎖(Exclusive),s表示共享鎖(Share),Y表示yes,N表示no)

  上圖表示可以共存的鎖,如,第二行表示,一個事務T1給某數據加了X鎖,則事務T2就不能再給那數據加X鎖了,同時也不能再加S鎖了,只有到T1事務提交完成之後,纔可以。默認來說,當sql腳本修改更新某條記錄的時候,會給該條記錄加X鎖,讀的話加的是S鎖。

  另外,併發操作會導致數據的不一致性,主要包括“丟失數據”,“不可重複讀”,“讀髒數據等。(詳細可看 王珊 版 數據庫系統概論第十一章 併發控制)。

  還有就是,併發控制會造成活鎖和死鎖,就像操作系統那樣,會因爲互相等待而導致。活鎖指的是T1封鎖了數據R,T2同時也請求封鎖數據R,T3也請求封鎖數據R,當T1釋放了鎖之後,T3會鎖住R,T4也請求封鎖R,則T2就會一直等待下去,這種處理方法就是採用“先來先服務”策略;死鎖就是我等你,你又等我,雙方就會一直等待下去,比如:T1封鎖了數據R1,正請求對R2封鎖,而T2封住了R2,正請求封鎖R1,這樣就會導致死鎖,死鎖這種沒有完全解決的方法,只能儘量預防,預防的方法有:①一次封鎖發,指的是一次性把所需要的數據全部封鎖住,但是這樣會擴大了封鎖的範圍,降低系統的併發度;②順序封鎖發,指的是事先對數據對象指定一個封鎖順序,要對數據進行封鎖,只能按照規定的順序來封鎖,但是這個一般不大可能的。另外,系統如何判斷出現死鎖呢,畢竟出現死鎖不能一直乾等下去,要及時發現死鎖同時儘快解決出現的死鎖,診斷和判斷死鎖有兩種方法,一是超時法,二是等待圖法。超時法就是如果某個事物的等待時間超過指定時限,則判定爲出現死鎖;等待圖法指的是如果事務等待圖中出現了迴路,則判斷出現了死鎖。對於解決死鎖的方法,只能是撤銷一個處理死鎖代價最小的事務,釋放此事務持有的所有鎖,同時對撤銷的事務所執行的數據修改操作必須加以恢復。

  最後,說下行級鎖和表級鎖。(一下摘自:http://blog.sina.com.cn/s/blog_548bd2090100ir7k.html

鎖包括行級鎖和表級鎖

行級鎖是一種排他鎖,防止其他事務修改此行;在使用以下語句時,Oracle會自動應用行級鎖:
INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT];
SELECT … FOR UPDATE語句允許用戶一次鎖定多條記錄進行更新
使用COMMIT或ROLLBACK語句釋放鎖

表級鎖又分爲5類:

行共享 (ROW SHARE) – 禁止排他鎖定表
行排他(ROW EXCLUSIVE) – 禁止使用排他鎖和共享鎖
共享鎖(SHARE) - 鎖定表,對記錄只讀不寫,多個用戶可以同時在同一個表上應用此鎖
共享行排他(SHARE ROW EXCLUSIVE) – 比共享鎖更多的限制,禁止使用共享鎖及更高的鎖
排他(EXCLUSIVE) – 限制最強的表鎖,僅允許其他用戶查詢該表的行。禁止修改和鎖定表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章