眾所周知,innodb是默認(rèn)行鎖,當(dāng)然也支持表鎖。如下是對(duì)于行鎖的算法進(jìn)行的一些實(shí)驗(yàn)。

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到穆棱網(wǎng)站設(shè)計(jì)與穆棱網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:做網(wǎng)站、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、空間域名、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋穆棱地區(qū)。
鎖的算法為:我知道是行鎖,但是是如何鎖的,鎖多少數(shù)據(jù)
假如有個(gè)索引是:[1,2,3,7]
record lock 鎖的是 1,2,3,7
gap lock 鎖的是 (- ,1),(2,3),(3,7),(7,+ )反正鎖的就是區(qū)間,不是行
next-key lock鎖的是 (- ,1],[2,3),[3,7),[ 7,+ )既鎖范圍也鎖行
Innodb鎖算法規(guī)則如下:
在可重復(fù)讀隔離級(jí)別下,innodb默認(rèn)使用的是next-key lock算法,當(dāng)查詢的索引是主鍵或者唯一索引的情況下,才會(huì)退化為record lock,在使用next-key lock算法時(shí),不僅僅會(huì)鎖住范圍,還會(huì)給范圍最后的一個(gè)鍵值加一個(gè)gap lock。
其中l(wèi)ockmode中的X鎖為左邊會(huì)話中的鎖,因?yàn)樾枰@式的commit之后才會(huì)釋放鎖,第二個(gè)S鎖,為右邊的共享鎖,因?yàn)橹麈IID為1的已經(jīng)被鎖住了,所以處于鎖等待狀態(tài),鎖的類型為record lock
使用輔助索引a=8進(jìn)行操作,這個(gè)時(shí)候理論應(yīng)該對(duì)主鍵索引加record lock 則 主鍵ID=8的被鎖,然后輔助索引被加next-key lock 則為:
(7,8] 然后對(duì)下一個(gè)鍵值加gap鎖,則為:(8,11)
所以目前被鎖住的記錄為:
1.主鍵為8的被鎖
2.輔助索引8的被鎖
3.輔助索引8到11之間的被鎖,意味著你這個(gè)時(shí)候往8到11之間寫(xiě)數(shù)據(jù)會(huì)報(bào)錯(cuò)
當(dāng)使用范圍條件進(jìn)行更新時(shí),此時(shí)肯定是需要加X(jué)鎖的,我是用的也是主鍵,所以按照理論應(yīng)該是加的record lock ,但是卻加了gap lock,因?yàn)椴迦胫禐?0的阻塞了,查看information 也提示X.GAP
這個(gè)有點(diǎn)暈為啥主鍵變成了next-key lock ,不應(yīng)該是record lock么?
update20200515
在知乎看到的一個(gè)解釋:
即,在無(wú)論使用主鍵索引還是非主鍵索引的時(shí)候,請(qǐng)求共享鎖或者排他鎖,innodb會(huì)給范圍內(nèi)的記錄加鎖,而范圍內(nèi)的間隙也會(huì)被加鎖,
例如一個(gè)表t 的 id為1,2,3,7,10
假如執(zhí)行如下:
select * from t where id =3 for update
那么這個(gè)時(shí)候執(zhí)行
insert into t(id) values(8) 會(huì)被阻塞,因?yàn)槭窃谡?qǐng)求排他鎖時(shí)使用了范圍,所以[3,10],甚至10以后的任何數(shù)據(jù)都無(wú)法插入。
執(zhí)行
select * from t where id =3 lock in share mode
insert into t(id) values(8) 會(huì)被阻塞,因?yàn)槭窃谡?qǐng)求共享鎖時(shí)使用了范圍,所以[3,10],甚至10以后的任何數(shù)據(jù)都無(wú)法插入。
幻讀是同一事務(wù)下,連續(xù)執(zhí)行兩次同樣的sql可能導(dǎo)致不同的結(jié)果,第二次返回的數(shù)據(jù)可能導(dǎo)致以前不存在的行。
同時(shí)一般會(huì)問(wèn)它和臟讀的區(qū)別,臟讀為讀取到其他事務(wù)未提交的數(shù)據(jù),但是幻讀是讀取的其他事務(wù)已經(jīng)提交的數(shù)據(jù)。
reference:
mysql 為并發(fā)事務(wù)同時(shí)對(duì)一條記錄進(jìn)行讀寫(xiě)時(shí),提出了兩種解決方案:
1)使用 mvcc 的方法,實(shí)現(xiàn)多事務(wù)的并發(fā)讀寫(xiě),但是這種讀只是“快照讀”,一般讀的是歷史版本數(shù)據(jù),還有一種是“當(dāng)前讀”,一般加鎖實(shí)現(xiàn)“當(dāng)前讀”,或者 insert、update、delete 也是當(dāng)前讀。
2)使用加鎖的方法,鎖分為共享鎖(讀鎖),排他鎖(寫(xiě)鎖)
快照讀:就是select
當(dāng)前讀:特殊的讀操作,插入/更新/刪除操作,屬于當(dāng)前讀,處理的都是當(dāng)前的數(shù)據(jù),需要加鎖。
mysql 在 RR 級(jí)別怎么處理幻讀的呢?一般來(lái)說(shuō),RR 級(jí)別通過(guò) mvcc 機(jī)制,保證讀到低于后面事務(wù)的數(shù)據(jù)。但是 select for update 不會(huì)觸發(fā) mvcc,它是當(dāng)前讀。如果后面事務(wù)插入數(shù)據(jù)并提交,那么在 RR 級(jí)別就會(huì)讀到插入的數(shù)據(jù)。所以,mysql 使用 行鎖 + gap 鎖(簡(jiǎn)稱 next-key 鎖)來(lái)防止當(dāng)前讀的時(shí)候插入。
Gap Lock在InnoDB的唯一作用就是防止其他事務(wù)的插入操作,以此防止幻讀的發(fā)生。
Innodb自動(dòng)使用間隙鎖的條件:
for update 的作用是在查詢的時(shí)候?yàn)樾屑由吓潘i,當(dāng)一個(gè)事務(wù)的操作未完成時(shí)候,其他事務(wù)可以讀取但是不能寫(xiě)入或更新。
它的典型使用場(chǎng)景是 高并發(fā)并且對(duì)于數(shù)據(jù)的準(zhǔn)確性有很高要求 ,比如金錢(qián)、庫(kù)存等,一般這種操作都是很長(zhǎng)一串并且開(kāi)啟事務(wù)的,假如現(xiàn)在要對(duì)庫(kù)存進(jìn)行操作,在剛開(kāi)始讀的時(shí)候是1,然后馬上另外一個(gè)進(jìn)程將庫(kù)存更新為0了,但事務(wù)還沒(méi)結(jié)束,會(huì)一直用1進(jìn)行后續(xù)的邏輯,就會(huì)有問(wèn)題,所以需要用for upate 加鎖防止出錯(cuò)。
行鎖的具體實(shí)現(xiàn)算法有三種:record lock、gap lock以及next-key lock。
只在可重復(fù)讀或以上隔離級(jí)別下的特定操作才會(huì)取得 gap lock 或 next-key lock,在 Select、Update 和 Delete 時(shí),除了基于唯一索引的查詢之外,其它索引查詢時(shí)都會(huì)獲取 gap lock 或 next-key lock,即鎖住其掃描的范圍。主鍵索引也屬于唯一索引,所以主鍵索引是不會(huì)使用 gap lock 或 next-key lock
for update 僅適用于InnoDB,并且必須開(kāi)啟事務(wù),在begin與commit之間才生效。
select 語(yǔ)句默認(rèn)不獲取任何鎖,所以是可以讀被其它事務(wù)持有排它鎖的數(shù)據(jù)的!
InnoDB 既實(shí)現(xiàn)了行鎖,也實(shí)現(xiàn)了表鎖。
當(dāng)有明確指定的主鍵/索引時(shí)候,是行級(jí)鎖,否則是表級(jí)鎖
假設(shè)表 user,存在有id跟name字段,id是主鍵,有5條數(shù)據(jù)。
明確指定主鍵,并且有此記錄,行級(jí)鎖
無(wú)主鍵/索引,表級(jí)鎖
主鍵/索引不明確,表級(jí)鎖
明確指定主鍵/索引,若查無(wú)此記錄,無(wú)鎖
參考博文:
名稱欄目:mysql怎么加一個(gè)行鎖 廣西青聯(lián)委員
URL標(biāo)題:http://chinadenli.net/article42/dojdeec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、App設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站收錄、網(wǎng)站導(dǎo)航、域名注冊(cè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)