在乙個高併發的資料庫系統裡,可能會遇到多個事務同一時刻修改某條資料的情況,這樣就產生了資源衝突,解決衝突就需要用到鎖。
一、鎖一說到鎖,就可能會聯想到樂觀鎖、悲觀鎖、共享鎖(讀鎖)、排他鎖(互斥鎖/寫鎖)、行級鎖、表級鎖 等一堆名詞,那它們之間到底有什麼區別和聯絡呢?其實很簡單,樂觀鎖和悲觀鎖是一種加鎖的思想;行級鎖和表級鎖是鎖的粒度,表示加鎖的範圍;而共享鎖和排他鎖才是真正的鎖,用來鎖住資料。下面我們分別討論一下它們。
1.1 樂觀鎖和排他鎖
鎖名機制
實現原理
優點缺點
適用場景
樂觀鎖整個資料處理過程都不加鎖,直到處理完準備提交時,才通過版本號檢查資料是否過期
大多是基於資料版本( version )記錄機制實現,即為每條資料增加乙個記錄版本號的字段,讀取資料時,將版本號一同讀出,更新時對此版本號加一,此時若提交的資料版本號大於資料庫表當前版本號,則予以更新,否則認為資料已經被其它事務修改過,需要回滾和重試
避免了加鎖的開銷和死鎖的出現,提高了系統的併發效能
來自外部系統的更新操作不受控制
適用於寫操作比較少,資料衝突較少的場景
悲觀鎖資料處理開始時就對資料加鎖,直到處理完成才釋放鎖
需要利用資料庫本身提供的鎖機制來實現,例如共享鎖、排他鎖
外部系統的更新操作也受控制,最大限度的為資料處理的安全性提供了保證
加鎖開銷大,增加產生死鎖的可能性,大大降低系統的併發效能
適用於寫操作比較多,資料衝突嚴重的場景
1.2 表級鎖和行級鎖
表級鎖和行級鎖是一種鎖的粒度。一般來說,鎖粒度越小,鎖衝突就越少,系統的併發效能就更高,但同時資料庫在管理鎖方面的開銷也越大,當管理鎖的開銷比資料訪問的開銷還要大時,反而可能會影響到系統的效能。
在mysql中,每個儲存引擎都可以有自己的鎖策略,例如myisam引擎僅支援表級鎖,而innodb引擎除了支援表級鎖外,也支援行級鎖(預設)。行級鎖可以最大程度地支援併發處理。
1.3 共享鎖和排他鎖
鎖名機制
共享鎖1.當事務a對某資源加了共享鎖後,其它事務也只能對該資源加共享鎖
2.若想加排他鎖,需等待所有事務釋放共享鎖
3.持有共享鎖的事務,都可以讀取該資源,但不能修改
排他鎖1.當事務a對某資源加了排他鎖後,事務a可以讀取和修改該資源
2.其它事務不能對該資源加任何鎖,直到事務a釋放排他鎖
共享鎖和排他鎖是悲觀鎖不同的實現,它倆都屬於悲觀鎖的範疇。在mysql innodb中,update/insert/delete操作都會自動加排他鎖,普通的select語句不會加任何鎖,如果想加鎖,可以使用下面方式:
select * from table_name where id = 1
lock
in share mode;
-- 顯式加共享鎖
select * from table_name where id = 1
forupdate;
-- 顯式加排他鎖
二、多版本併發控制(mvcc)
不同的資料庫實現mvcc的方式是不一樣的,因為mvcc沒有乙個統一的實現標準,這裡我們只談論mysql innodb中的mvcc。
2.1 為什麼需要mvcc
innodb採用的是兩階段鎖定協議,事務執行過程中,根據需要不斷的加鎖,最後commit或rollback的時候一次性釋放所有鎖,實質上是一種悲觀併發控制(悲觀鎖),而悲觀鎖會降低系統的併發效能。為了提高併發效能,innodb同時還實現了多版本併發控制(mvcc)。
2.2 mvcc的實現原理
簡單來說,mvcc就是同一條資料可以同時存在多個版本:更新資料時,先插入一條新記錄,然後把舊記錄標記為刪除;刪除資料時將記錄標記為刪除;查詢時只查詢事務開始前就已存在的記錄。詳細的實現就不展開講了,網上有很多相關資料,詳情可以參考這個**,或者參閱《高效能mysql第三版》1.4章節。
2.3 mvcc解決的問題
通過了解實現原理,可以看出mvcc解決了這些問題:
聊一聊 MySQL 資料庫中的那些鎖
在軟體開發中,程式在高併發的情況下,為了保證一致性或者說安全性,我們通常都會通過加鎖的方式來解決,在 mysql 資料庫中同樣有這樣的問題,一方面為了最大程度的利用資料庫的併發訪問,另一方面又需要保證每個使用者能以一致的方式讀取和修改資料,就引入了鎖機制。全域性鎖是粒度最大的鎖,基本上也使用不上,就...
聊一聊MyISAM和InnoDB的區別
主要有以下區別 1 mysql預設採用的是myisam。2 myisam不支援事務,而innodb支援。innodb的autocommit預設是開啟的,即每條sql語句會預設被封裝成乙個事務,自動提交,這樣會影響速度,所以最好是把多條sql語句顯示放在begin和commit之間,組成乙個事務去提交...
聊一聊 MYSQL 資料的真刪和假刪
簡單做個小白文描述。真刪,我們就不展開了。該篇文章其實主要是想聊聊 這個假刪 邏輯刪除 既然是對某張表做了假刪,使用 status 那麼在一些業務 查詢裡面 切記切記一定不能忘了,只要使用到 假刪 的資料表,那麼需要帶上 status 0 驗重,字面意思就是說資料唯一,而這個資料的唯一保證 我們常規...