1. 程式人生 > >mysql中的鎖的相關知識

mysql中的鎖的相關知識

不可重復讀 避免 並發 數據讀取 等待 並發控制 客戶端 提交 Language

數據庫鎖:數據庫鎖出現的原因是為了處理並發問題。

並發控制一般采用三種方法,分別是樂觀鎖和悲觀鎖以及時間戳。

樂觀鎖認為一個用戶讀數據的時候,別人不會去寫自己所讀的數據,就是不做任何操作。悲觀鎖就剛好相反,覺得自己讀數據庫的時候,別人可能剛好在寫自己剛讀的數據,其實就是持一種比較保守的態度,悲觀鎖就是在讀取數據的時候,為了不讓別人修改自己讀取的數據,就會先對自己讀取的數據加鎖,只有自己把數據讀完了,才允許別人修改那部分數據,或者反過來說,就是自己修改某條數據的時候,不允許別人讀取該數據,只有等自己的整個事務提交了,才釋放自己加上的鎖,才允許其他用戶訪問那部分數據。悲觀鎖所說的加“鎖”。

悲觀鎖分為:

讀鎖/共享鎖:共享的鎖,多個客戶端可以同時讀取一個資源,互補幹擾。
寫鎖/排它鎖:一個鎖會阻塞其他的寫鎖和讀鎖,確保一個時刻只有一個客戶端對通過一個數據進行修改寫入。

時間戳就是在數據庫表中單獨加一列時間戳,比如“TimeStamp”,每次讀出來的時候,把該字段也讀出來,當寫回去的時候,把該字段加1,提交之前 ,跟數據庫的該字段比較一次,如果比數據庫的值大的話,就允許保存,否則不允許保存。

表鎖 是開銷比較小的策略,會鎖定整張表。MyISAM和InnoDB都支持表級鎖定。用戶對表進行寫操作,需要先獲得鎖,並且會阻塞用戶對該表的所有讀操作。 數據庫中對表進行修改,如alter table會使用到表鎖,會鎖定整張表,因此此類操作在數據庫中應該謹慎使用。

行鎖 行鎖可以高效的支持並發,當然鎖開銷也是最大。MySQL的InnoDB引擎中實現了行鎖,在用戶寫數據時,只鎖定需要操作的數據行,相比於表鎖並發度更好。

InnoDB支持事務,

事務是數據庫區別於文件系統的額重要特性之一。事務符合ACID特性。原子性:原子性是指數據庫事務是不可分割的工作單位。只有數據庫事務中的所有數據庫操作執行都成功,才算整個事務成功。如果事務中的任何一個SQL語句執行失敗,已經執行的SQL語句也必須撤銷,數據庫狀態退回到執行事務前的狀態。

一致性:事務執行之前和之後,數據庫的完整性約束沒有被破壞。

隔離性:一個事物的影響在它提交前對其他事務不可見(通過鎖來實現)

持久性:事務一旦提交,其結果就是永久性的。

原子性,一致性,持久性通過redo,undo來完成。

並發事務所帶來的問題:

  • 更新丟失(Lost Update):當兩個事務T1和T2讀入同一數據做修改並發執行時,T2把T1或T1把T2的修改結果覆蓋掉,造成數據的丟失更新問題,導致數據的不一致。
  • 臟讀(Dirty Reads):事務T1更新了數據R,事務T2讀取了更新後的數據R,事務T1由於某種原因被撤銷,恢復數據R。這樣T2讀取的數據和數據庫中內容不一樣。
  • 不可重復讀(Non-Repeatable Reads):一個事務對同一行數據讀取了兩次,結果不同。
  • (1)事務T1讀取了數據R,事務T2讀取並更新了R,當事務再讀取R進行核對時,兩次讀取的值不一樣。
  • (2)事務操作過程中進行了兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的數據或缺少了第一次查詢的數據,這種情況稱為幻讀。

間隙鎖(Next-Key鎖)

當我們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫做“間隙(GAP)”,InnoDB也會對這個“間隙”加鎖,這種鎖機制不是所謂的間隙鎖(Next-Key鎖)。 舉例來說,假如emp表中只有101條記錄,其empid的值分別是1,2,...,100,101,下面的SQL: SELECT * FROM emp WHERE empid > 100 FOR UPDATE 是一個範圍條件的檢索,InnoDB不僅會對符合條件的empid值為101的記錄加鎖,也會對empid大於101(這些記錄並不存在)的“間隙”加鎖。 InnoDB使用間隙鎖的目的,一方面是為了防止幻讀,以滿足相關隔離級別的要求,對於上面的例子,要是不使用間隙鎖,如果其他事務插入了empid大於100的任何記錄,那麽本事務如果再次執行上述語句,就會發生幻讀;另一方面,是為了滿足其恢復和復制的需要。有關其恢復和復制對機制的影響,以及不同隔離級別下InnoDB使用間隙鎖的情況。 很顯然,在使用範圍條件檢索並鎖定記錄時,InnoDB這種加鎖機制會阻塞符合條件範圍內鍵值的並發插入,這往往會造成嚴重的鎖等待。因此,在實際開發中,尤其是並發插入比較多的應用,我們要盡量優化業務邏輯,盡量使用相等條件來訪問更新數據,避免使用範圍條件。

死鎖

兩個用戶分別鎖定一個資源,之後雙方又都等待雙方釋放所鎖定的資源,就產生一個鎖定請求環,從而出現死鎖。死鎖往往出現在行級鎖中。

如何解決死鎖?

在InnoDB的事務管理和鎖定機制中,有專門用於檢測死鎖的機制。當檢測當死鎖時,InnoDB會選擇產生死鎖的兩個事務中的較小的一個完成回滾。

mysql中的鎖的相關知識