MySQL 鎖詳解
MySQL鎖機制
概述
按使用方式
樂觀鎖
概述
假設在極大多數情況下不會形成衝突,只有在數據提交的時候,纔會對數據是否產生衝突進行檢驗。如果數據產生衝突了,則返回錯誤信息,進行相應的處理。
處理辦法
- 使用版本號實現樂觀鎖
- 使用版本號時,可以在數據初始化時指定一個版本號,每次對數據的更新操作都對版本號執行+1操作。並判斷當前版本號是不是該數據的最新的版本號。
- 樂觀鎖不需要數據庫底層的支持
悲觀鎖
概述
悲觀鎖就是在操作數據時,認爲此操作會出現數據衝突,所以在進行每次操作時都要通過獲取鎖才能進行對相同數據的操作,這點跟java中的synchronized很相似,所以悲觀鎖需要耗費較多的時間。
處理辦法
- 必須關閉mysql數據庫的自動提交屬性,因爲MySQL默認使用autocommit模式
- 悲觀鎖是由數據庫自己實現了的,要用的時候,我們直接調用數據庫的相關語句就可以了
鎖類型
- mysql在執行insert、update會自動加鎖,mysql對select卻不會加鎖
- 共享鎖
- 其它事務可以讀但是不能寫
- SQL 寫法 - 顯式加鎖
select * from table where column_name = ‘columnValue’ LOCK IN SHARE MODE
- SQL 寫法 - 隱式加鎖
select * from table where column_name = ‘columnValue’
- 排它鎖
- 只有自己的事務有權限對此數據進行讀寫嗎,其它的事務不可讀不可寫
- SQL 寫法
select * from table where column_name = ‘columnValue’ FOR UPDATE
按鎖粒度區分
表級鎖
概述
表級鎖是 MySQL 中鎖定粒度最大的一種鎖,表示對當前操作的整張表加鎖,它實現簡單,資源消耗較少,被大部分 MySQL 引擎支持。表級鎖定分爲表共享讀鎖(共享鎖)與表獨佔寫鎖(排他鎖)
特點
- 開銷小,加鎖快
- 不會出現死鎖
- 一次性同時獲取所有需要的鎖
- 總是按相同的順序來獲取表鎖
- 鎖定粒度大,發出鎖衝突的概率最高,併發度最低
- 適合於以查詢爲主,併發用戶少,只有少量按索引條件更新數據場景
被存儲引擎支持的類型
- MyISAM
- MEMORY
- BDB(頁級鎖)
- InnoDB(行級鎖)
行級鎖
概述
鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖分爲共享鎖和排他鎖
特點
- 開銷大,加鎖慢
- 可能出現死鎖
- 單個SQL的事務不會發生死鎖
- 多個SQL組成的事務可能發生死鎖
- 鎖是按順序逐步獲取的
- 鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高
- 只在存儲引擎層實現,MySQL沒有實現
- 適合於有大量按索引條件併發更新少量不同數據,同時又有併發查詢的場景
被存儲引擎支持的類型
- InnoDB(行級鎖)
頁級鎖
概述
鎖定粒度介於行級鎖和表級鎖中間的一種鎖。採取了折衷的頁級鎖,一次鎖定相鄰的一組記錄
特點
- 開銷和加鎖時間界於表鎖和行鎖之間
- 可能出現死鎖
- 單個SQL的事務不會發生死鎖
- 多個SQL組成的事務可能發生死鎖
- 鎖是按順序逐步獲取的
- 鎖定粒度界於表鎖和行鎖之間,併發度一般。
被存儲引擎支持的類型
- BDB(頁級鎖)