資料庫的鎖

2021-10-09 15:35:49 字數 2238 閱讀 9638

innodb 除了支援行級鎖,還支援由 mysql 服務層實現的表級鎖(lock tables … write在指定的表加上表級排他鎖)。當這兩種鎖同時存在時,可能導致衝突。例如,事務 a 獲取了表中一行資料的讀鎖;然後事務 b 申請該錶的寫鎖(例如修改表的結構)。如果事務 b 加鎖成功,那麼它就應該能修改表中的任意資料行,但是 a 持有的行鎖不允許修改鎖定的資料行。顯然資料庫需要避免這種問題,b 的加鎖申請需要等待 a 釋放行鎖。

那麼如何判斷事務 b 是否應該獲取表級鎖呢?首先需要看該錶是否已經被其他事務加上了表級鎖,然後依次檢視該表中的每一行是否已經被其他事務加上了行級鎖。這種方式需要遍歷整個表中的記錄,效率很低。為此,innodb 引入了另外一種鎖:意向鎖(intention lock)。

意向鎖屬於表級鎖,由 innodb 自動新增,不需要使用者干預。意向鎖也分為共享和排他兩種方式:

此時,事務 a 必須先申請該錶的意向共享鎖,成功後再申請資料行的行鎖。事務 b 申請表鎖時,資料庫檢視該錶是否已經被其他事務加上了表級鎖;如果發現該錶上存在意向共享鎖,說明表中某些資料行上存在共享鎖,事務 b 申請的寫鎖會被阻塞。

因此,意向鎖是為了使得行鎖和表鎖能夠共存,從而實現多粒度的鎖機制。

間隙鎖(gap lock)鎖定的是索引記錄之間的間隙、第乙個索引之前的間隙或者最後乙個索引之後的間隙。例如,select * from t where c1 between 1 and 10 for update;會阻止其他事務將 1 到 10 之間的任何值插入到 c1 欄位中,即使該列不存在這樣的資料;因為這些值都會被鎖定。

next-key 鎖(next-key lock)相當於乙個索引記錄鎖加上該記錄之前的乙個間隙鎖。參考

首先要明確:無論是悲觀鎖還是樂觀鎖,都是人們定義出來的概念,可以認為是一種思想。其實不僅僅是關係型資料庫中有樂觀鎖和悲觀鎖的概念,像hibernate、tair、memcache等都有類似的概念。所以,不應該拿樂觀鎖、悲觀鎖和其他的資料庫鎖進行對比。樂觀鎖比較適用於讀多寫少的情況(多讀場景),悲觀鎖比較適用於寫多讀少的情況(多寫場景)。

當要對資料庫中的一條資料進行修改的時候,為了避免同時被其他人修改,最好的辦法就是直接對該資料進行加鎖以防止併發。這種借助資料庫鎖機制,在修改資料之前先鎖定,再修改的方式被稱之為悲觀併發控制【pessimistic concurrency control,縮寫「pcc」,又名「悲觀鎖」】。

悲觀鎖,正如其名,具有強烈的獨佔和排他特性。它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度。因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

之所以叫做悲觀鎖,是因為這是一種對資料的修改持有悲觀態度的併發控制方式。總是假設最壞的情況,每次讀取資料的時候都預設其他執行緒會更改資料,因此需要進行加鎖操作,當其他執行緒想要訪問資料時,都需要阻塞掛起。悲觀鎖的實現:

傳統的關係型資料庫使用這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

悲觀併發控制實際上是「先取鎖再訪問」的保守策略,為資料處理的安全提供了保證。但是在效率方面,處理加鎖的機制會讓資料庫產生額外的開銷,還有增加產生死鎖的機會。另外還會降低並行性,乙個事務如果鎖定了某行資料,其他事務就必須等待該事務處理完才可以處理那行資料。

樂觀鎖是相對悲觀鎖而言的,樂觀鎖假設資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則返回給使用者錯誤的資訊,讓使用者決定如何去做。樂觀鎖適用於讀操作多的場景,這樣可以提高程式的吞吐量。

樂觀鎖的實現:

資料庫mvcc

樂觀併發控制相信事務之間的資料競爭(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時候才去鎖定,所以不會產生任何鎖和死鎖。

悲觀鎖的實現,往往以考資料庫提供的鎖機制。在資料庫中,悲觀鎖的流程如下:

在對記錄進行修改前,先嘗試為該記錄加上排他鎖(exclusive locks)。

如果加鎖失敗,說明該記錄正在被修改,那麼當前查詢可能要等待或者丟擲異常。具體響應方式由開發者根據實際需要決定。

如果成功加鎖,那麼就可以對記錄做修改,事務完成後就會解鎖了。

如果成功加鎖,那麼就可以對記錄做修改,事務完成後就會解鎖了。

以常用的mysql innodb引擎為例,來說明下在sql中如何使用悲觀鎖。

樂觀鎖與悲觀鎖

資料庫的鎖

相當好的文章!希望以後結合實踐再好好理解。innodb中的事務隔離級別和鎖的關係 mysql faq 系列 如何檢視當前最新事務id mysql 對於千萬級的大表要怎麼優化?鎖有悲觀鎖和樂觀鎖。悲觀鎖中分共享鎖和排他鎖。在事務中,讀資料的時候加分享鎖 其他事務還可以加分享鎖,但是不能加排他鎖 寫資料...

資料庫的鎖

鎖是用於管理對共享資源的併發訪問,是資料庫系統區別於檔案系統的乙個關鍵特性 本文主要來談innodb引擎,innodb引擎支援行鎖 表鎖粒度的鎖 為了支援多粒度鎖定,innodb 儲存引擎引入了意向鎖 intention lock 意向鎖是表級鎖 什麼是意向鎖呢?如果沒有意向鎖,當已經有人使用行鎖對...

資料庫的鎖

資料庫的鎖用來鎖住資料庫中的某些資料,使得當前只能有乙個使用者 會話可以更新資料。所以,資料庫的鎖用來防止同時有乙個或多個使用者更新同一塊資料。當資料被鎖起來,這意味著另乙個資料庫會話在鎖釋放之前不能更新這塊被鎖起來的資料。畫重點 假如會話a嘗試訪問被會話b鎖起來的資料,會話a會發生什麼?會話a會被...