InnoDB實現了兩種類型的行鎖。數據庫
共享鎖(S):容許一個事務去讀一行,阻止其餘事務得到相同的數據集的排他鎖。併發
排他鎖(X):容許得到排他鎖的事務更新數據,可是組織其餘事務得到相同數據集的共享鎖和排他鎖。優化
簡單來講spa
共享鎖就是我讀的時候,你能夠讀,可是不能寫。3d
排他鎖就是我寫的時候,你即不能讀也不能寫。blog
除此以外InnoDB還有兩個表鎖:索引
意向共享鎖(IS):表示事務準備給數據行加入共享鎖,也就是說一個數據行加共享鎖前必須先取得該表的IS鎖事務
意向排他鎖(IX):相似上面,表示事務準備給數據行加入排他鎖,說明事務在一個數據行加排他鎖前必須先取得該表的IX鎖。ip
注意:意向鎖是InnoDB自動加的,不須要用戶干預。it
對於insert、update、delete,操做
InnoDB會自動給涉及的數據加排他鎖;而對於通常的Select語句,InnoDB不會加任何鎖(若是沒有鎖 也就是 select …… from where…… (沒有額外加鎖後綴)使用MVCC(multiple-version-concurrency-control)是行級鎖的變種,它在普通讀狀況下避免了加鎖操做,所以開銷更低)可是咱們能夠經過如下語句給select加共享鎖或排他鎖。
共享鎖:select * from table_name where ..... lock in share mode
排他鎖:select * from table_name where .....for update
下面我將舉例說明【注意:須要關閉自動提交事務 set autocommit = 0】
加入共享鎖(我讀的時候,你能夠讀,可是不能寫)
事務1 |
事務2 |
開啓事務 start transaction;
|
開啓事務 start transaction; |
查詢id=1而且加入共享鎖 select * from test where id = 1 lock in share mode;
|
查詢id=1而且加入共享鎖 select * from test where id = 1 lock in share mode;
|
更新此條紀錄,發現鎖被佔用等待
其餘事務退出之後 更新成功
|
也去更新 致使死鎖退出
|
|
加入排他鎖 這裏就不演示了。
具體鎖的實現原理
InnoDB行鎖是經過給索引項加鎖實現的,若是沒有索引,InnoDB會經過隱藏的聚簇索引來對記錄加鎖。
InnoDB這種行鎖實現特色意味着:只有經過索引條件檢索數據,InnoDB才使用行級鎖,不然,InnoDB將使用表鎖!
行鎖分爲三種情形:
Record lock :對索引項加鎖,即鎖定一條記錄。
Gap lock:對索引項之間的‘間隙’、對第一條記錄前的間隙或最後一條記錄後的間隙加鎖,即鎖定一個範圍的記錄,不包含記錄自己 (InnoDB使用間隙鎖的目的,主要爲了防止幻讀)
Next-key Lock:鎖定一個範圍的記錄幷包含記錄自己(上面二者的結合)。
注意:InnoDB默認級別是repeatable-read級別,因此下面說的都是在RR級別中的。
Next-Key Lock是行鎖與間隙鎖的組合,這樣,當InnoDB掃描索引記錄的時候,
當咱們用範圍條件查詢數據,會首先對選中的索引記錄加上行鎖(Record Lock),再對索引記錄兩邊的間隙加上間隙鎖(Gap Lock)。若是一個間隙被事務T1加了鎖,其它事務是不能在這個間隙插入記錄的。
下面舉例說明
假如數據庫有如下3條記錄
好比 我要查詢
Select * frm test where id>2 for update,
這個時候InnoDB不只會對符合條件的id值爲3的記錄加鎖,也會對id大於3(這些記錄並不存在)的「間隙」加鎖。
注意:::
當咱們在使用範圍條件檢索並鎖定記錄時,InnoDB這種加鎖機制會阻塞符合條件範圍內鍵值的併發插入,這每每會形成嚴重的鎖等待。
所以,尤爲是併發插入比較多的應用,
咱們要儘可能優化業務邏輯,儘可能使用相等條件來訪問數據,避免使用範圍條件。