日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

谈谈InnoDB下的记录锁,间隙锁,next-key锁

發布時間:2025/3/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 谈谈InnoDB下的记录锁,间隙锁,next-key锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

innodb下的記錄鎖(也叫行鎖),間隙鎖,next-key鎖統統屬于排他鎖。行鎖,即記錄鎖,其實很好理解,對表中的記錄加鎖,叫做記錄鎖,簡稱行鎖。就不多做介紹,主要介紹間隙鎖,next-key鎖。

間隙鎖

間隙鎖,顧名思義就是存在間隙,在間隙之間上鎖保證在間隙間不可以進行操作。舉一個生活中比較好理解得例子,A,B,C依次排成一排,為了讓新來的D不能插在B的旁邊,只要將B和A之間的空隙封鎖,將B和C之間的空隙封鎖,那么D就不能插在B的旁邊了。他們之間的空隙也就是間隙,而封鎖他們之間距離的鎖,叫做間隙鎖。這里映射到數據庫層面,A,B,C,D就是數據庫的一條條記錄。

Mysql中的間隙鎖

假設數據庫中某個表存在以下數據,其中id為主鍵,number字段上有非唯一索引的二級索引,有什么方式可以讓該表不能再插入number=5的記錄呢?

id(主鍵)number(二級索引)
12
34
65
85
105
1311

由之前的概念可以想到,只要控制number=5之前不能插入記錄,number=5現有的記錄之間不能再插入新的記錄,number=5之后不能插入新的記錄,那么新的number=5的記錄將不能被插入進來。那么,mysql是如何控制number=5之前,之中,之后不能有新的記錄插入呢(防止幻讀)?答案是用間隙鎖。
在RR級別下,mysql通過間隙鎖可以實現鎖定number=5之前的間隙,number=5記錄之間的間隙,number=5之后的間隙,從而使的新的記錄無法被插入進來。間隙鎖要通過兩個方面實現防止幻讀:

  • 防止間隙內有新數據被插入
  • 防止已存在的數據,更新成間隙內的數據
    接下來帶大家來理解一下具體的含義。

間隙鎖的間隙劃分

為了方便理解,我們規定(id=A,number=B)代表一條字段id=A,字段number=B的記錄,(C,D)代表一個區間,代表C-D這個區間范圍。所以在上圖中,根據number列,可以分為幾個區間:(無窮小,2),(2,4),(4,5),(5,5),(5,11),(11,無窮大)。只要這些區間對應的兩個臨界記錄中間可以插入記錄,就認為區間對應的記錄之間有間隙。例如區間(2,4)分別對應的臨界記錄是(id=1,number=2),(id=3,number=4),這兩條記錄中間可以插入(id=2,number=3)等記錄,那么就認為(id=1,number=2)與(id=3,number=4)之間存在間隙。同理(id=6,number=5)與(id=8,number=5)之間可以插入記錄(id=7,number=5),因此(id=6,number=5)與(id=8,number=5)之間有間隙的。

間隙鎖的鎖定區域

根據檢索條件向左尋找最靠近檢索條件的記錄值A,作為左區間,向右尋找最靠近檢索條件的記錄值B作為右區間,即鎖定的間隙為(A,B)。如上圖中,where number=5的話,那么間隙鎖的區間范圍為(4,11)。

間隙鎖的實際操作

接下來我們通過幾個具體的例子來觀察下間隙鎖的作用范圍。

實際操作一

有如下兩個事務操作,我們分析一下當session 1執行的時候,session 2中的insert操作是否可以執行成功。

session 1: start transaction ; select * from news where number=4 for update ;session 2: start transaction ; insert into news value(2,4); insert into news value(2,2); insert into news value(4,4); insert into news value(4,5); insert into news value(7,5); insert into news value(9,5); insert into news value(11,5);

檢索條件number=4,向左取得最靠近的值2作為左區間,向右取得最靠近的5作為右區間,因此,session 1的間隙鎖的范圍(2,4),(4,5),如下圖所示:

間隙鎖鎖定的區間為(2,4),(4,5),即記錄(id=1,number=2)和記錄(id=3,number=4)之間間隙會被鎖定,記錄(id=3,number=4)和記錄(id=6,number=5)之間間隙被鎖定。因此記錄(id=2,number=4),(id=2,number=2),(id=4,number=4),(id=4,number=5)正好處在(id=3,number=4)和(id=6,number=5)之間,所以插入不了,需要等待鎖的釋放,而記錄(id=7,number=5),(id=9,number=5),(id=11,number=5)不在上述鎖定的范圍內,因此都會插入成功。

session 2: start transaction ; insert into news value(2,4);#(阻塞) insert into news value(2,2);#(阻塞) insert into news value(4,4);#(阻塞) insert into news value(4,5);#(阻塞) insert into news value(7,5);#(執行成功) insert into news value(9,5);#(執行成功) insert into news value(11,5);#(執行成功)

實際操作二

有如下兩個事務操作,我們同樣來分析一下當session 1執行的時候,session 2中的insert操作是否可以執行成功。

session 1: start transaction ; select * from news where number=13 for update ;session 2: start transaction ; insert into news value(11,5); insert into news value(12,11); insert into news value(14,11); insert into news value(15,12); update news set id=14 where number=11; update news set id=11 where number=11;

檢索條件number=13,向左取得最靠近的值11作為左區間,向右由于沒有記錄因此取得無窮大作為右區間,因此,session 1的間隙鎖的范圍(11,無窮大),如下圖所示:

此表中沒有number=13的記錄的,innodb依然會為該記錄左右兩側加間隙鎖,間隙鎖的范圍(11,無窮大)。因此記錄(id=11,number=5),(id=12,number=11),(id=11,number=11),處在(id=13,number=11)之前,所以會插入成功,而記錄(id=14,number=11),(id=15,number=12),(id=14,number=11)在上述鎖定的范圍內,因此操作阻塞,需要等待鎖的釋放。

session 2: start transaction ; insert into news value(11,5);#(執行成功) insert into news value(12,11);#(執行成功) insert into news value(14,11);#(阻塞) insert into news value(15,12);#(阻塞) update news set id=14 where number=11;#(阻塞) update news set id=11 where number=11;#(執行成功)

可能有人還是不太明白,為啥update news set id=14 where number=11會阻塞,但是update news set id=11 where number=11卻執行成功呢?間隙鎖采用在指定記錄的前面和后面以及中間的間隙上加間隙鎖的方式避免數據被插入,此圖間隙鎖鎖定的區域是(11,無窮大),也就是記錄(id=13,number=11)之后不能再插入記錄,update news set id=14 where number=11這條語句如果執行的話,將會被插入到(id=13,number=11)的后面,也就是在區間(11,無窮大)之間,由于該區間被間隙鎖鎖定,所以只能阻塞等待,而update news set id=11 where number=11執行后是會被插入到(id=13,number=11)的記錄前面,也就不在(11,無窮大)的范圍內,所以無需等待,執行成功。

實際操作三

有如下兩個事務操作,我們同樣來分析一下當session 1執行的時候,session 2中的insert操作是否可以執行成功。

session 1: start transaction ; select * from news where number=5 for update;session 2: start transaction ; insert into news value(4,4); insert into news value(4,5); insert into news value(5,5); insert into news value(7,11); insert into news value(9,12); insert into news value(12,11); update news set number=5 where id=1; update news set id=11 where number=11; update news set id=2 where number=4 ; update news set id=4 where number=4 ;

檢索條件number=5,向左取得最靠近的值4作為左區間,向右取得11為右區間,因此,session 1的間隙鎖的范圍(4,5),(5,11),如下圖所示:

依據之前的分析方法,我想大家很快就可以得到一下的結論:

session 2: start transaction ; insert into news value(4,4);#(阻塞) insert into news value(4,5);#(阻塞) insert into news value(5,5);#(阻塞) insert into news value(7,11);#(阻塞) insert into news value(9,12);#(執行成功) insert into news value(12,11);#(阻塞) update news set number=5 where id=1;#(阻塞) update news set id=11 where number=11;#(阻塞) update news set id=2 where number=4 ;#(執行成功) update news set id=4 where number=4 ;#(阻塞)

有人會問,為啥insert into news value(9,12)會執行成功?間隙鎖采用在指定記錄的前面和后面以及中間的間隙上加間隙鎖的方式避免數據被插入,(id=9,number=12)很明顯在記錄(13,11)的后面,因此不再鎖定的間隙范圍內。而為啥update news set number=5 where id=1會阻塞?number=5的記錄的前面,后面包括中間都被封鎖了,你這個update news set number=5 where id=1根本沒法執行,因為innodb已經把你可以存放的位置都鎖定了,因為只能等待。同理,update news set id=11 where number=11由于記錄(id=10,number=5)與記錄(id=13,number=11)中間的間隙被封鎖了,你這句sql也沒法執行,必須等待,因為存放的位置被封鎖了。

實際操作三

有如下兩個事務操作,我們同樣來分析一下當session 1執行的時候,session 2中的insert操作是否可以執行成功。

session 1: start transaction; select * from news where number>4 for update;session 2: start transaction; update news set id=2 where number=4 ; update news set id=4 where number=4 ; update news set id=5 where number=5 ; insert into news value(2,3); insert into news value(null,13);

檢索條件number>4,向左取得最靠近的值4作為左區間,向右取無窮大,因此,session 1的間隙鎖的范圍(4,無窮大),如下圖所示:

同樣依據之前的分析方式,也很容易得出以下的結論:

session 2: start transaction; update news set id=2 where number=4 ;#(執行成功) update news set id=4 where number=4 ;#(阻塞) update news set id=5 where number=5 ;#(阻塞) insert into news value(2,3);#(執行成功) insert into news value(null,13);#(阻塞)

next-key鎖

next-key鎖其實包含了記錄鎖和間隙鎖,即鎖定一個范圍,并且鎖定記錄本身,InnoDB默認加鎖方式是next-key 鎖。例如上面的實際操作一中的session 1的sql:

select * from news where number=4 for update ;

next-key鎖鎖定的范圍為間隙鎖+記錄鎖,即在區間(2,4),(4,5)加間隙鎖,同時number=4的記錄加記錄鎖。比較簡單,就不做過多敘述。

猜你感興趣
MYSQL專題-絕對實用的MYSQL優化總結
MYSQL專題-MySQL事務實現原理
MYSQL專題-MVCC多版本并發控制
MYSQL專題-MySQL三大日志binlog、redo log和undo log

更多文章請點擊:更多…

參考文章:
https://www.jianshu.com/p/bf862c37c4c9

總結

以上是生活随笔為你收集整理的谈谈InnoDB下的记录锁,间隙锁,next-key锁的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。