Mysql中那些鎖機制之InnoDB

2021-08-11 08:30:51 字數 3568 閱讀 4803

我們知道mysql在以前,儲存引擎預設是myisam,但是隨著對事務和併發的要求越來越高,便引入了innodb引擎,它具有支援事務安全等一系列特性。

innodb實現了兩種型別的行鎖。

共享鎖(s):允許乙個事務去讀一行,阻止其他事務獲得相同的資料集的排他鎖。

排他鎖(x):允許獲得排他鎖的事務更新資料,但是組織其他事務獲得相同資料集的共享鎖和排他鎖。

可以這麼理解:

共享鎖就是我讀的時候,你可以讀,但是不能寫。排他鎖就是我寫的時候,你不能讀也不能寫。其實就是myisam的讀鎖和寫鎖,但是針對的物件不同了而已。

除此之外innodb還有兩個表鎖:

意向共享鎖(is):表示事務準備給資料行加入共享鎖,也就是說乙個資料行加共享鎖前必須先取得該錶的is鎖

意向排他鎖(ix):類似上面,表示事務準備給資料行加入排他鎖,說明事務在乙個資料行加排他鎖前必須先取得該錶的ix鎖。

innodb行鎖模式相容列表:

注意:

當乙個事務請求的鎖模式與當前的鎖相容,innodb就將請求的鎖授予該事務;反之如果請求不相容,則該事務就等待鎖釋放。

意向鎖是innodb自動加的,不需要使用者干預。

對於insert、update、delete,innodb會自動給涉及的資料加排他鎖(x);對於一般的select語句,innodb不會加任何鎖,事務可以通過以下語句給顯示加共享鎖或排他鎖。

共享鎖:select * from table_name where .....lock in share mode

排他鎖:select * from table_name where .....for update

加入共享鎖的例子:

利用select ....for update加入排他鎖

innodb行鎖是通過給索引項加鎖實現的,如果沒有索引,innodb會通過隱藏的聚簇索引來對記錄加鎖。

也就是說:如果不通過索引條件檢索資料,那麼innodb將對錶中所有資料加鎖,實際效果跟表鎖一樣。

行鎖分為三種情形:

record lock:對索引項加鎖,即鎖定一條記錄。

gap lock:對索引項之間的『間隙』、對第一條記錄前的間隙或最後一條記錄後的間隙加鎖,即鎖定乙個範圍的記錄,不包含記錄本身

next-key lock:鎖定乙個範圍的記錄幷包含記錄本身(上面兩者的結合)。

注意:innodb預設級別是repeatable-read級別,所以下面說的都是在rr級別中的。

之前一直搞不懂gap lock和next-key lock的區別,直到在網上看到一句話豁然開朗,希望對各位有幫助。

next-key lock是行鎖與間隙鎖的組合,這樣,當innodb掃瞄索引記錄的時候,會首先對選中的索引記錄加上行鎖(record lock),再對索引記錄兩邊的間隙加上間隙鎖(gap lock)。如果乙個間隙被事務t1加了鎖,其它事務是不能在這個間隙插入記錄的。

乾巴巴的說沒意思,我們來看看具體例項:

假設我們有一張表:

+----+------+

| id | age |

+----+------+

| 1 | 3 |

| 2 | 6 |

| 3 | 9 |

+----+------+

表結構如下:

create table `test` (

`id` int(11) not null auto_increment,

`age` int(11) default null,

primary key (`id`),

key `keyname` (`age`)

) engine=innodb auto_increment=302 default charset=gbk ;

這樣我們age段的索引就分為

(negative infinity, 3],

(3,6],

(6,9],

(9,positive infinity);

我們來看一下幾種情況:

1、當事務a執行以下語句:

mysql> select * from fenye where age=6for update ;

不僅使用行鎖鎖住了相應的資料行,同時也在兩邊的區間,(5,6]和(6,9] 都加入了gap鎖。

這樣事務b就無法在這個兩個區間insert進新資料,但是事務b可以在兩個區間外的區間插入資料。

2、當事務a執行

select * from fenye where age=7 for update ;

那麼就會給(6,9]這個區間加鎖,別的事務無法在此區間插入或更新資料。

3、如果查詢的資料不再範圍內,

比如事務a執行select * from fenye where age=100 for update ;

那麼加鎖區間就是(9,positive infinity)。

小結:行鎖防止別的事務修改或刪除,gap鎖防止別的事務新增,行鎖和gap鎖結合形成的的next-key鎖共同解決了rr級別在寫資料時的幻讀問題。

innodb在絕大部分情況會使用行級鎖,因為事務和行鎖往往是我們選擇innodb的原因,但是有些情況我們也考慮使用表級鎖。

1、當事務需要更新大部分資料時,表又比較大,如果使用預設的行鎖,不僅效率低,而且還容易造成其他事務長時間等待和鎖衝突。

2、事務比較複雜,很可能引起死鎖導致回滾。

我們說過myisam中是不會產生死鎖的,因為myisam總是一次性獲得所需的全部鎖,要麼全部滿足,要麼全部等待。而在innodb中,鎖是逐步獲得的,就造成了死鎖的可能。

在上面的例子中我們可以看到,當兩個事務都需要獲得對方持有的鎖才能夠繼續完成事務,導致雙方都在等待,產生死鎖。

發生死鎖後,innodb一般都可以檢測到,並使乙個事務釋放鎖回退,另乙個獲取鎖完成事務。

避免死鎖:

有多種方法可以避免死鎖,這裡只介紹常見的三種:

1、如果不同程式會併發訪問多個表,盡量約定以相同的順序訪問表,可以大大降低死鎖機會。

2、在同乙個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產生概率;

3、對於非常容易產生死鎖的業務部分,可以嘗試使用公升級鎖定顆粒度,通過表級鎖定來減少死鎖產生的概率;

mysql 簡述鎖機制 MySQL之鎖機制簡述

一 為什麼需要鎖 鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。為了保證資料庫中資料併發訪問的一致性 有效性,故引入鎖機制。其中鎖衝突也是影響資料庫併發訪問效能的乙個重要因素。二 鎖的分類 分類一 行鎖,頁鎖,表鎖 分類二 共享鎖 排他鎖 意向鎖 is ix 分類三 樂觀鎖 悲觀鎖 inno...

MySQL中鎖機制

mysql儲存引擎 mysql索引 mysql鎖機制 myisam和memory採用的是表級鎖,bdb採用頁面鎖,innodb既支援行級鎖,也支援表級鎖,預設使用行級鎖。表共享讀鎖,表獨佔寫鎖 進行查詢時自動加讀鎖,進行插入,更新,刪除會自動加寫鎖,不需要顯式寫出 lock table table ...

鎖機制之MySQL表鎖

如何保證在被併發訪問時資料的一致性 完整性和有效性,是資料庫關注的核心問題。資料庫的鎖機制就是為了解決這個問題而出現的。鎖機制在一定程度上將對共享資源的併發訪問有序化,從而保證資料的一致完整性。鎖機制的好壞直接影響到資料的併發處理能力和效能。乙個好的鎖機制的實現是乙個資料的核心競爭力之一。我們知道在...