還是通過例子,假設(shè)事務(wù) A 獲取了 student 表中 id = 100 這行的共享鎖,之后事務(wù) B 需要申請(qǐng) student 表的排他鎖。而這兩把鎖明顯是沖突的,而且還是對(duì)于同一行。
那 InnoDB 需要如何感知 A 獲取了這把鎖?遍歷整個(gè) B+ 樹嗎?不,答案就是意向鎖。事務(wù) B 申請(qǐng)寫表的排他鎖時(shí),InnoDB 會(huì)發(fā)現(xiàn)事務(wù) A 已經(jīng)獲取了該表的意向共享鎖,說明 student 表中已經(jīng)有記錄被共享鎖鎖住了。此時(shí)就會(huì)阻塞住。
當(dāng)我們執(zhí)行SELECT * FROM student WHERE id = 1 FOR UPDATE語句時(shí),就會(huì)對(duì)值為1的索引加上記錄鎖。至于要是一張表里沒有索引該怎么辦?這個(gè)問題在上面提到的文章中也解釋過了,當(dāng)一張表沒有定義主鍵時(shí),InnoDB 會(huì)創(chuàng)建一個(gè)隱藏的RowID,并以此 RowID 來創(chuàng)建聚簇索引。后續(xù)的記錄鎖也會(huì)加到這個(gè)隱藏的聚簇索引上。
當(dāng)我們開啟一個(gè)事務(wù)去更新 id = 1 這行數(shù)據(jù)時(shí),如果我們不馬上提交事務(wù),然后再啟一個(gè)事務(wù)去更新 id = 1 的行,此時(shí)使用 show engine innodb status查看,我們可以看到lock_mode X locks rec but not gap waiting的字樣。
X是排他鎖的意思,從這可以看出來,記錄鎖其實(shí)也可以分為共享鎖、排他鎖模式。當(dāng)我們使用FOR UPDATE是排他,而使用LOCK IN SHARE MODE 則是共享。
值得注意的是,這里的 age 不是唯一索引,就是一個(gè)簡單的非聚簇索引。此時(shí)會(huì)給 age = 10 的數(shù)據(jù)加上記錄鎖,并且鎖定 age 10 的 Gap。如果當(dāng)前這個(gè)事務(wù)不提交,其他事務(wù)如果要插入一條 age 10 的數(shù)據(jù)時(shí),會(huì)被阻塞住。
間隙鎖是 MySQL 在對(duì)性能、并發(fā)綜合考慮之下的一種折中的解決方案,并且只在**可重復(fù)讀(RR)下可用,如果當(dāng)前事務(wù)的隔離級(jí)別為讀已提交(RC)**時(shí),MySQL會(huì)將間隙鎖禁用。
最后是自增鎖(AUTO-INC Locks),自增鎖的本質(zhì)是表鎖,較為特殊。當(dāng)事務(wù) A 向包含了 AUTO_INCREMENT 列的表中新增數(shù)據(jù)時(shí),就會(huì)持有自增鎖。而此時(shí)其他的事務(wù) B 則必須要等待,以保證事務(wù) A 取得連續(xù)的自增值,中間不會(huì)有斷層。
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《簡單了解 MySQL 中相關(guān)的鎖》,本文關(guān)鍵詞 簡單,了解,MySQL,中,相關(guān),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。