事務隔離性
當多個線程都開啓事務操做數據庫中數據時,數據庫系統要能進行隔離操做,以保證各個線程獲取數據的準確性。數據庫
若是沒有隔離,會發生的幾種問題
髒讀(Dirty Read)併發
一個事務處理過程裏讀取了另外一個未提交的事務中的數據性能
不可重複讀(NonRepeatable Read)spa
對於數據庫中的某個數據,一個事務範圍內屢次查詢卻返回了不一樣的數據值,這是因爲在查詢的間隔期間,另一個事務修改並提交了該數據。線程
不可重複讀和髒讀的區別是,髒讀是某一事務讀取了另外一個事務未提交的髒數據,而不可重複讀則是讀取了前一事務提交的數據。blog
在某些狀況下,不可重複讀並非問題,好比咱們屢次查詢某個數據固然以最後查詢獲得的結果爲主。但在另外一些狀況下就有可能發生問題,例如對於同一個數據A和B依次查詢就可能不一樣,A和B就可能打起來了……。索引
幻讀(Phantom Read)事務
在一個事務中讀取到了別的事務插入的數據,致使先後不一致。it
事務A 按照必定條件進行數據讀取,期間事務B插入了相同搜索條件的新數據,事務A再次按照原先條件進行讀取時,發現了事務B 新插入的數據。table
不一樣隔離級別的問題
MySQL的鎖類型
表鎖
對一整張表加鎖,併發能力低下(即便有分讀鎖、寫鎖),通常在DDL處理時使用,myisam也是表鎖。
行鎖
只鎖住特定行的數據,併發能力強,MySQL通常都是用行鎖來處理併發事務。
若是用到無索引的字段,那麼MySQL會在存儲引擎層面將全部的記錄加鎖,而後由MySQL Server過濾,若是不知足會調用unlock_row把不知足條件的記錄釋放鎖(這裏違背了二段鎖協議)。
這種狀況一樣適用於MySQL的默認隔離級別RR。因此對一個數據量很大的表作批量修改的時候,若是沒法使用相應的索引,MySQL Server過濾數據的的時候特別慢,就會出現雖然沒有修改某些行的數據,可是它們仍是被鎖住了的現象。
GAP鎖(間隙鎖)
MySQL使用索引對行鎖兩邊的區間進行加鎖,避免其餘事務在這兩個區間insert的一種鎖。
如圖所示:數據庫中存在值5,30。那麼數據庫會將數據段切分如下幾個區間:
(negative infinity, 5],
(5,30],
(30,positive infinity)
當對值爲30這一行加行鎖的時候,會同時對(5,30]和(30,positive infinity)加GAP鎖。這樣其餘事務若是想在這兩個區間進行insert操做的時候,須要等待本次事務完成。
若是對不存在的數據進行更新,好比更新20(不存在)對應數據行,那麼數據庫也會對其存在的區間(5,30]加GAP鎖。這樣,若是有其餘事務想插入值爲10的數據,須要等待20這個事務完成。
若是使用的是沒有索引的字段,那麼會給全表加入GAP鎖。
Next-Key鎖
Next-Key鎖是行鎖和GAP鎖的合併(MySQL使用它來避免幻讀)
MVVC(多版本併發控制)
Innodb中的樂觀鎖實現。經過它提升MySQL的讀取操做的性能。並能解決MySQL的重複讀問題。
MVVC在每一行記錄的後面加兩個隱含列(記錄建立版本號和刪除版本號)。這裏的版本號指的是事務的版本號(每一個事務啓動的時候,都有一個遞增的版本號)。
Innodb中事務隔離級別和鎖的關係
Innodb經過使用不一樣的鎖來實現事務隔離
避免髒讀
經過對數據加行鎖或則表鎖,使對同一數據進行操做的事務處於等待狀態,來避免同時操做
避免不可重複讀
經過MVVC實現事務的可重複讀
避免幻讀
經過Next-Key鎖避免產生幻讀現象。
MySQL在RC和RR中都避免了幻讀現象。
----------------------------------------------------------------------------------------------
悲觀鎖
樂觀鎖
在衝突比較少的時候採用樂觀鎖,減小不須要加鎖釋放鎖的開銷,能夠提升性能。
在衝突比較多的時候採用悲觀鎖,減小重複嘗試次數,樂觀鎖重複操做的代價比較大。