mysql知識盤點【陸】_鎖和事務級別

系列文章:

mysql知識盤點【壹】_SQL優化

mysql知識盤點【貳】_InnoDB引擎索引

mysql知識盤點【叄】_主從複製

mysql知識盤點【肆】_調優參數

mysql知識盤點【伍】_執行計劃

 

1.鎖

innodb存儲引擎支持4種鎖:

S:共享鎖,可認爲對一行數據的讀鎖;

X:排他鎖,可認爲對一行數據的寫鎖;

IS:意向共享鎖,事務想獲得一張表中幾行數據的共享鎖;

IX:意向排他鎖,事務想獲得一張表中幾行數據的排他鎖;

 

對於意向鎖我們可以這樣理解。基於前面的文章我們知道,sql的數據存儲分爲如下幾個層次:首先是段segment,可先認爲一張表即一個段;段下面有若干區extent,區是一個虛擬單位,默認包含16個頁page;一個頁默認64KB,具體的數據行就保存在頁中。如果一個事務想對某行數據上X鎖,那麼它分別需要先對數據所在的表(段)和頁上意向鎖IX。如果上某一部分的意向鎖需要等待,那麼整個事務需要一起等待。

 

各種鎖的兼容性如下: 

 

2.事務隔離級別

一般數據庫事務隔離級別有4種:讀未提交、讀已提交、可重複讀、串行,總結如下:

此圖只做展示用
(此圖只做展示用)

其中,

髒讀是指讀取到了其他事務未提交的數據;

不可重複讀是指當其他事務提交數據更新,導致當前事務中連續兩次對數據的獲取值不同;

幻讀是指當其他事務新增數據,導致當前事務中連續兩次對數據的獲取,第二次返回了之前不存在的行;

 

我們知道innodb採用的是行鎖,共提供了3種行鎖算法:

record lock:單行記錄上鎖;

gap lock:間隙鎖,開區間;

next-key lock:包含record lock和gap lock,半開半閉區間;

 

其中record lock是基於聚集索引來實現,如果一張表沒有設置主鍵,則根據隱式主鍵rowId來實現。

可重複讀事務隔離級別默認使用next-key lock鎖,當判斷條件是主鍵且爲等價判斷,則降級爲record lock鎖,否則範圍查詢或非主鍵條件查詢則是next-key lock鎖。正式通過這種鎖區間的方式,innodb的可重複讀事務隔離級別下避免了幻讀問題,這也是innodb存儲引擎下可重複讀事務隔離級別和其他數據庫不一樣的地方。

 

3.Innodb的事務方案

innodb存儲引擎對於事務提供了redo和undo兩種日誌。

redo log記錄的是每個頁內數據更改的物理情況,在一個事務未提交之前會多次提交。當設備斷電等情況,可用作數據恢復。它的存在,保證了ACID中的A和D。

undo log記錄的是數據每次變更的版本。這裏補充一下,mysql會爲每條數據記錄生成rowId(主鍵不存在時)、trxId(事務id)和roll_ptr(回滾指針)等不可見列。當事務中一行數據發生變成時,innodb會將該行數據修改前的版本保存到undo log中,包含trxId。如果事務發生回滾,則直接恢復到undo log中指定的版本即可。

mysql的MVCC實現,也正式基於undo log。這裏就涉及到上面說的數據庫隔離級別,讀已提交和可重讀讀,在innodb是如何實現的。在讀已提交級別下,事務每次讀undo log都是最新版本的trxId,則可能出現不可重複讀問題;但是在可重複讀級別下,事務每次讀undo log都是指定版本的trxId,這樣可能出現讀取的不是最新數據,但是可以保證每次讀取出的數據是一樣的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章