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