Mysql的InnoDB儲存引擎鎖機制

2023-01-19 10:40:33 字數 3017 閱讀 3886

事務用來保證資料庫的完整性——要麼都修改,要麼都不修改。事務必須滿足acid四個特性。

iso和anis sql標準制定了四種事務隔離級別的標準:

innodb既支援行級鎖,也支援表級鎖,預設情況下是採用行級鎖。

innodb儲存引擎實現了兩種標準的行級鎖:

一致性的非鎖定讀(consistent nonlocking read)是指innodb儲存引擎通過多版本控制(multi versioning)的方式來讀取當前執行時間資料庫中行的資料。如果讀取的行正在執行delete、update操作,這是讀取操作不會因此而等待行上鎖的釋放,相反,innodb儲存引擎會去讀取行的一個快照資料。如下圖所示:

上圖可以看出,讀取的資料是一份快照資料,快照資料是指執行當前更改操作前的資料,該實現是通過undo段來實現的,所以快照資料本身是沒有額外的開銷的。因為快照資料是一份歷史資料,是隻讀的,所以不需要上鎖。

快照可能有多個版本,也就是說可能有多份不同的快照資料,這種技術稱為行多版本技術,由此帶來的併發控制稱為多版本併發控制(multi version concurrency control, mvcc)

一致性非鎖定讀是innodb儲存引擎預設的讀取方式,但是不同的事務隔離級別下,讀取的方式不同,並不是每個事務隔離級別下讀取的都是一致性讀,即使都是一致性讀,不同的事務隔離級別讀取的快照資料也不同。例如read commited和repeatable read下,使用的都是一致性的非鎖定讀,但它們讀取的是不同的快照資料。在read commited級別下,讀取的總是被鎖定行的最新一份快照資料,而在repeatable read級別下,讀取的是事務開始時的第一份快照資料。

step 1. 初始化測試表

mysql> create table t (id int,

-> primary key (id))

-> engine innodb;

query ok, 0 rows affected (0.62 sec)

mysql> insert into t values(1);

mysql> select * from t;

+----+

| id |

+----+

| 1 |

+----+

1 row in set (0.00 sec)

step 2. 開啟一個會話a,並在會話a中開啟一個事務,檢視下測試表的資料,但不提交事務

# session a

mysql> begin;

query ok, 0 rows affected (0.03 sec)

mysql> select * from t;

+----+

| id |

+----+

| 1 |

+----+

1 row in set (0.00 sec)

step 3. 開啟另一個會話b,模擬併發的情況,在會話b中開啟事務,修改測試表中id為1的資料,但不提交

# session b

mysql> begin ;

query ok, 0 rows affected (0.00 sec)

mysql> update t set id = 3 where id = 1;

query ok, 1 row affected (0.00 sec)

rows matched: 1 changed: 1 warnings: 0

step 4. 在會話a中檢視測試表資料,發現還是修改之前的資料

# session a

mysql> select * from t;

+----+

| id |

+----+

| 1 |

+----+

1 row in set (0.00 sec)

setp 5. 在會話b中提交事務

# session b

mysql> commit;

query ok, 0 rows affected (0.04 sec)

step 5. 再在會話a中檢視測試資料,在read commited和repeatable read級別下得到的結果就不一樣了。對於read committed級別,它總是讀取最新版本,所以它得到的結果是一個id為3的記錄(幻讀)。而repeatable read級別下,它總是讀取事務開始時的行資料,所以它得到的結果仍然是一個id為1的記錄。

預設情況下,innodb儲存引擎的select操作使用的是一致性非鎖定讀,但是有些情況下,需要使用者主動對讀取操作進行加鎖。innodb儲存引擎對select語句加鎖有兩種操作:

innodb儲存引擎有3種行鎖演算法:

多個事務同時修改同一行記錄,可能出現丟失更新的問題。

事務a查詢了一行資料。

事務b也查詢了這行資料。

事務a根據它的查詢結果修改資料,並提交事務。

事務b根據它的查詢結果修改資料,並提交事務。

可以看出,事務1的更新操作丟失了。避免丟失更新的做法,就是事務在查詢資料的時候加上排他鎖。

髒讀是指事務a讀到了事務b中還沒有提交的更新(違反了資料庫的隔離性)。髒讀只在隔離級別為read uncommitted的情況下才會發生。避免髒讀的辦法,就是把事務的隔離級別至少設定成read committed。

幻讀是指在一個事務中多次讀同一資料,拿到的結果不同(違反了資料庫的一致性)。例如,事務a讀了一行資料,事務b修改了這行資料並提交了,事務a再讀這行資料,拿到的結果與事務a前一次讀取的結果不同。

幻讀一般是可以接收的,因為它讀到的確實是其他事務已經提交的資料。

innodb儲存引擎中,通過使用next-key lock演算法來避免幻讀問題。在next-key lock演算法下,對於索引的掃描,不僅僅鎖住的是掃描到的索引,而且還鎖住這些索引覆蓋的範圍(gap),因此在這個範圍內的修改都是不允許的。

Mysql的InnoDB儲存引擎中的鎖

本文主要內容 介紹innodb中的鎖的型別 x s ix is 解釋為什麼引入意向鎖 行鎖的三種演算法 record lock,gap lock,next key lock 鎖,在現實生活中是為我們想要隱藏於外界所使用的一種工具。在計算機中,是協調多個程序或縣城併發訪問某一資源的一種機制。在資料庫當...

MySql中innodb儲存引擎事務日誌詳解

mysql會最大程度的使用快取機制來提高資料庫的訪問效率,但是萬一資料庫發生斷電,因為快取的資料沒有寫入磁碟,導致快取在記憶體中的資料丟失而導致資料不一致怎麼辦?innodb主要是通過事務日誌實現acid特性,事務日誌包括 重做日誌redo和回滾日誌undo。redo記錄的是已經全部完成的事務,就是...

MySQL之InnoDB儲存引擎的鎖

innodb儲存引擎實現兩種標準的行級鎖 鎖相容 意向鎖此外,innodb 儲存引擎支援多粒度 granular 鎖定,這種鎖定允許事務在行級上的鎖和表級上的鎖同時存在。為了支援在不同粒度上進行加鎖操作,innodb 儲存引擎支援一種額外的鎖方式,稱之為意向鎖 intention lock 意向鎖是...