日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

說(shuō)說(shuō)MySQL有哪些鎖

小林coding ? 來(lái)源:小林coding ? 作者:小林coding ? 2022-10-24 10:15 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

正文

這次,來(lái)說(shuō)說(shuō) MySQL 的鎖,主要是 Q&A 的形式,看起來(lái)會(huì)比較輕松。

不多 BB 了,發(fā)車(chē)!

在 MySQL 里,根據(jù)加鎖的范圍,可以分為全局鎖、表級(jí)鎖和行鎖三類(lèi)。

3f9dae58-528a-11ed-a3b6-dac502259ad0.png

全局鎖

全局鎖是怎么用的?

要使用全局鎖,則要執(zhí)行這條命:

flushtableswithreadlock

執(zhí)行后,整個(gè)數(shù)據(jù)庫(kù)就處于只讀狀態(tài)了,這時(shí)其他線(xiàn)程執(zhí)行以下操作,都會(huì)被阻塞:

對(duì)數(shù)據(jù)的增刪改操作,比如 insert、delete、update等語(yǔ)句;

對(duì)表結(jié)構(gòu)的更改操作,比如 alter table、drop table 等語(yǔ)句。

如果要釋放全局鎖,則要執(zhí)行這條命令:

unlocktables

當(dāng)然,當(dāng)會(huì)話(huà)斷開(kāi)了,全局鎖會(huì)被自動(dòng)釋放。

全局鎖應(yīng)用場(chǎng)景是什么?

全局鎖主要應(yīng)用于做全庫(kù)邏輯備份,這樣在備份數(shù)據(jù)庫(kù)期間,不會(huì)因?yàn)閿?shù)據(jù)或表結(jié)構(gòu)的更新,而出現(xiàn)備份文件的數(shù)據(jù)與預(yù)期的不一樣。

舉個(gè)例子大家就知道了。

在全庫(kù)邏輯備份期間,假設(shè)不加全局鎖的場(chǎng)景,看看會(huì)出現(xiàn)什么意外的情況。

如果在全庫(kù)邏輯備份期間,有用戶(hù)購(gòu)買(mǎi)了一件商品,一般購(gòu)買(mǎi)商品的業(yè)務(wù)邏輯是會(huì)涉及到多張數(shù)據(jù)庫(kù)表的更新,比如在用戶(hù)表更新該用戶(hù)的余額,然后在商品表更新被購(gòu)買(mǎi)的商品的庫(kù)存。

那么,有可能出現(xiàn)這樣的順序:

先備份了用戶(hù)表的數(shù)據(jù);

然后有用戶(hù)發(fā)起了購(gòu)買(mǎi)商品的操作;

接著再備份商品表的數(shù)據(jù)。

也就是在備份用戶(hù)表和商品表之間,有用戶(hù)購(gòu)買(mǎi)了商品。

這種情況下,備份的結(jié)果是用戶(hù)表中該用戶(hù)的余額并沒(méi)有扣除,反而商品表中該商品的庫(kù)存被減少了,如果后面用這個(gè)備份文件恢復(fù)數(shù)據(jù)庫(kù)數(shù)據(jù)的話(huà),用戶(hù)錢(qián)沒(méi)少,而庫(kù)存少了,等于用戶(hù)白嫖了一件商品。

所以,在全庫(kù)邏輯備份期間,加上全局鎖,就不會(huì)出現(xiàn)上面這種情況了。

加全局鎖又會(huì)帶來(lái)什么缺點(diǎn)呢?

加上全局鎖,意味著整個(gè)數(shù)據(jù)庫(kù)都是只讀狀態(tài)。

那么如果數(shù)據(jù)庫(kù)里有很多數(shù)據(jù),備份就會(huì)花費(fèi)很多的時(shí)間,關(guān)鍵是備份期間,業(yè)務(wù)只能讀數(shù)據(jù),而不能更新數(shù)據(jù),這樣會(huì)造成業(yè)務(wù)停滯。

既然備份數(shù)據(jù)庫(kù)數(shù)據(jù)的時(shí)候,使用全局鎖會(huì)影響業(yè)務(wù),那有什么其他方式可以避免?

有的,如果數(shù)據(jù)庫(kù)的引擎支持的事務(wù)支持可重復(fù)讀的隔離級(jí)別,那么在備份數(shù)據(jù)庫(kù)之前先開(kāi)啟事務(wù),會(huì)先創(chuàng)建 Read View,然后整個(gè)事務(wù)執(zhí)行期間都在用這個(gè) Read View,而且由于 MVCC 的支持,備份期間業(yè)務(wù)依然可以對(duì)數(shù)據(jù)進(jìn)行更新操作。

因?yàn)樵诳芍貜?fù)讀的隔離級(jí)別下,即使其他事務(wù)更新了表的數(shù)據(jù),也不會(huì)影響備份數(shù)據(jù)庫(kù)時(shí)的 Read View,這就是事務(wù)四大特性中的隔離性,這樣備份期間備份的數(shù)據(jù)一直是在開(kāi)啟事務(wù)時(shí)的數(shù)據(jù)。

備份數(shù)據(jù)庫(kù)的工具是 mysqldump,在使用 mysqldump 時(shí)加上 –single-transaction 參數(shù)的時(shí)候,就會(huì)在備份數(shù)據(jù)庫(kù)之前先開(kāi)啟事務(wù)。這種方法只適用于支持「可重復(fù)讀隔離級(jí)別的事務(wù)」的存儲(chǔ)引擎。

InnoDB 存儲(chǔ)引擎默認(rèn)的事務(wù)隔離級(jí)別正是可重復(fù)讀,因此可以采用這種方式來(lái)備份數(shù)據(jù)庫(kù)。

但是,對(duì)于 MyISAM 這種不支持事務(wù)的引擎,在備份數(shù)據(jù)庫(kù)時(shí)就要使用全局鎖的方法。

表級(jí)鎖

MySQL 表級(jí)鎖有哪些?具體怎么用的。

MySQL 里面表級(jí)別的鎖有這幾種:

表鎖;

元數(shù)據(jù)鎖(MDL);

意向鎖;

AUTO-INC 鎖;

表鎖

先來(lái)說(shuō)說(shuō)表鎖。

如果我們想對(duì)學(xué)生表(t_student)加表鎖,可以使用下面的命令:

//表級(jí)別的共享鎖,也就是讀鎖;
locktablest_studentread;

//表級(jí)別的獨(dú)占鎖,也就是寫(xiě)鎖;
locktablest_stuentwrite;

需要注意的是,表鎖除了會(huì)限制別的線(xiàn)程的讀寫(xiě)外,也會(huì)限制本線(xiàn)程接下來(lái)的讀寫(xiě)操作。

也就是說(shuō)如果本線(xiàn)程對(duì)學(xué)生表加了「共享表鎖」,那么本線(xiàn)程接下來(lái)如果要對(duì)學(xué)生表執(zhí)行寫(xiě)操作的語(yǔ)句,是會(huì)被阻塞的,當(dāng)然其他線(xiàn)程對(duì)學(xué)生表進(jìn)行寫(xiě)操作時(shí)也會(huì)被阻塞,直到鎖被釋放。

要釋放表鎖,可以使用下面這條命令,會(huì)釋放當(dāng)前會(huì)話(huà)的所有表鎖:

unlocktables

另外,當(dāng)會(huì)話(huà)退出后,也會(huì)釋放所有表鎖。

不過(guò)盡量避免在使用 InnoDB 引擎的表使用表鎖,因?yàn)楸礞i的顆粒度太大,會(huì)影響并發(fā)性能,InnoDB 牛逼的地方在于實(shí)現(xiàn)了顆粒度更細(xì)的行級(jí)鎖

元數(shù)據(jù)鎖

再來(lái)說(shuō)說(shuō)元數(shù)據(jù)鎖(MDL)。

我們不需要顯示的使用 MDL,因?yàn)楫?dāng)我們對(duì)數(shù)據(jù)庫(kù)表進(jìn)行操作時(shí),會(huì)自動(dòng)給這個(gè)表加上 MDL:

對(duì)一張表進(jìn)行 CRUD 操作時(shí),加的是 MDL 讀鎖

對(duì)一張表做結(jié)構(gòu)變更操作的時(shí)候,加的是 MDL 寫(xiě)鎖;

MDL 是為了保證當(dāng)用戶(hù)對(duì)表執(zhí)行 CRUD 操作時(shí),防止其他線(xiàn)程對(duì)這個(gè)表結(jié)構(gòu)做了變更。

當(dāng)有線(xiàn)程在執(zhí)行 select 語(yǔ)句( 加 MDL 讀鎖)的期間,如果有其他線(xiàn)程要更改該表的結(jié)構(gòu)( 申請(qǐng) MDL 寫(xiě)鎖),那么將會(huì)被阻塞,直到執(zhí)行完 select 語(yǔ)句( 釋放 MDL 讀鎖)。

反之,當(dāng)有線(xiàn)程對(duì)表結(jié)構(gòu)進(jìn)行變更( 加 MDL 寫(xiě)鎖)的期間,如果有其他線(xiàn)程執(zhí)行了 CRUD 操作( 申請(qǐng) MDL 讀鎖),那么就會(huì)被阻塞,直到表結(jié)構(gòu)變更完成( 釋放 MDL 寫(xiě)鎖)。

MDL 不需要顯示調(diào)用,那它是在什么時(shí)候釋放的?

MDL 是在事務(wù)提交后才會(huì)釋放,這意味著事務(wù)執(zhí)行期間,MDL 是一直持有的

那如果數(shù)據(jù)庫(kù)有一個(gè)長(zhǎng)事務(wù)(所謂的長(zhǎng)事務(wù),就是開(kāi)啟了事務(wù),但是一直還沒(méi)提交),那在對(duì)表結(jié)構(gòu)做變更操作的時(shí)候,可能會(huì)發(fā)生意想不到的事情,比如下面這個(gè)順序的場(chǎng)景:

首先,線(xiàn)程 A 先啟用了事務(wù)(但是一直不提交),然后執(zhí)行一條 select 語(yǔ)句,此時(shí)就先對(duì)該表加上 MDL 讀鎖;

然后,線(xiàn)程 B 也執(zhí)行了同樣的 select 語(yǔ)句,此時(shí)并不會(huì)阻塞,因?yàn)椤缸x讀」并不沖突;

接著,線(xiàn)程 C 修改了表字段,此時(shí)由于線(xiàn)程 A 的事務(wù)并沒(méi)有提交,也就是 MDL 讀鎖還在占用著,這時(shí)線(xiàn)程 C 就無(wú)法申請(qǐng)到 MDL 寫(xiě)鎖,就會(huì)被阻塞,

那么在線(xiàn)程 C 阻塞后,后續(xù)有對(duì)該表的 select 語(yǔ)句,就都會(huì)被阻塞,如果此時(shí)有大量該表的 select 語(yǔ)句的請(qǐng)求到來(lái),就會(huì)有大量的線(xiàn)程被阻塞住,這時(shí)數(shù)據(jù)庫(kù)的線(xiàn)程很快就會(huì)爆滿(mǎn)了。

為什么線(xiàn)程 C 因?yàn)樯暾?qǐng)不到 MDL 寫(xiě)鎖,而導(dǎo)致后續(xù)的申請(qǐng)讀鎖的查詢(xún)操作也會(huì)被阻塞?

這是因?yàn)樯暾?qǐng) MDL 鎖的操作會(huì)形成一個(gè)隊(duì)列,隊(duì)列中寫(xiě)鎖獲取優(yōu)先級(jí)高于讀鎖,一旦出現(xiàn) MDL 寫(xiě)鎖等待,會(huì)阻塞后續(xù)該表的所有 CRUD 操作。

所以為了能安全的對(duì)表結(jié)構(gòu)進(jìn)行變更,在對(duì)表結(jié)構(gòu)變更前,先要看看數(shù)據(jù)庫(kù)中的長(zhǎng)事務(wù),是否有事務(wù)已經(jīng)對(duì)表加上了 MDL 讀鎖,如果可以考慮 kill 掉這個(gè)長(zhǎng)事務(wù),然后再做表結(jié)構(gòu)的變更。

意向鎖

接著,說(shuō)說(shuō)意向鎖。

在使用 InnoDB 引擎的表里對(duì)某些記錄加上「共享鎖」之前,需要先在表級(jí)別加上一個(gè)「意向共享鎖」;

在使用 InnoDB 引擎的表里對(duì)某些紀(jì)錄加上「獨(dú)占鎖」之前,需要先在表級(jí)別加上一個(gè)「意向獨(dú)占鎖」;

也就是,當(dāng)執(zhí)行插入、更新、刪除操作,需要先對(duì)表加上「意向獨(dú)占鎖」,然后對(duì)該記錄加獨(dú)占鎖。

而普通的 select 是不會(huì)加行級(jí)鎖的,普通的 select 語(yǔ)句是利用 MVCC 實(shí)現(xiàn)一致性讀,是無(wú)鎖的。

不過(guò),select 也是可以對(duì)記錄加共享鎖和獨(dú)占鎖的,具體方式如下:

//先在表上加上意向共享鎖,然后對(duì)讀取的記錄加共享鎖
select...lockinsharemode;

//先表上加上意向獨(dú)占鎖,然后對(duì)讀取的記錄加獨(dú)占鎖
select...forupdate;

意向共享鎖和意向獨(dú)占鎖是表級(jí)鎖,不會(huì)和行級(jí)的共享鎖和獨(dú)占鎖發(fā)生沖突,而且意向鎖之間也不會(huì)發(fā)生沖突,只會(huì)和共享表鎖(lock tables ... read)和獨(dú)占表鎖(lock tables ... write)發(fā)生沖突。

表鎖和行鎖是滿(mǎn)足讀讀共享、讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥的。

如果沒(méi)有「意向鎖」,那么加「獨(dú)占表鎖」時(shí),就需要遍歷表里所有記錄,查看是否有記錄存在獨(dú)占鎖,這樣效率會(huì)很慢。

那么有了「意向鎖」,由于在對(duì)記錄加獨(dú)占鎖前,先會(huì)加上表級(jí)別的意向獨(dú)占鎖,那么在加「獨(dú)占表鎖」時(shí),直接查該表是否有意向獨(dú)占鎖,如果有就意味著表里已經(jīng)有記錄被加了獨(dú)占鎖,這樣就不用去遍歷表里的記錄。

所以,意向鎖的目的是為了快速判斷表里是否有記錄被加鎖。

AUTO-INC 鎖

表里的主鍵通常都會(huì)設(shè)置成自增的,這是通過(guò)對(duì)主鍵字段聲明 AUTO_INCREMENT 屬性實(shí)現(xiàn)的。

之后可以在插入數(shù)據(jù)時(shí),可以不指定主鍵的值,數(shù)據(jù)庫(kù)會(huì)自動(dòng)給主鍵賦值遞增的值,這主要是通過(guò) AUTO-INC 鎖實(shí)現(xiàn)的。

AUTO-INC 鎖是特殊的表鎖機(jī)制,鎖不是再一個(gè)事務(wù)提交后才釋放,而是再執(zhí)行完插入語(yǔ)句后就會(huì)立即釋放。

在插入數(shù)據(jù)時(shí),會(huì)加一個(gè)表級(jí)別的 AUTO-INC 鎖,然后為被 AUTO_INCREMENT 修飾的字段賦值遞增的值,等插入語(yǔ)句執(zhí)行完成后,才會(huì)把 AUTO-INC 鎖釋放掉。

那么,一個(gè)事務(wù)在持有 AUTO-INC 鎖的過(guò)程中,其他事務(wù)的如果要向該表插入語(yǔ)句都會(huì)被阻塞,從而保證插入數(shù)據(jù)時(shí),被 AUTO_INCREMENT 修飾的字段的值是連續(xù)遞增的。

但是, AUTO-INC 鎖再對(duì)大量數(shù)據(jù)進(jìn)行插入的時(shí)候,會(huì)影響插入性能,因?yàn)榱硪粋€(gè)事務(wù)中的插入會(huì)被阻塞。

因此, 在 MySQL 5.1.22 版本開(kāi)始,InnoDB 存儲(chǔ)引擎提供了一種輕量級(jí)的鎖來(lái)實(shí)現(xiàn)自增。

一樣也是在插入數(shù)據(jù)的時(shí)候,會(huì)為被 AUTO_INCREMENT 修飾的字段加上輕量級(jí)鎖,然后給該字段賦值一個(gè)自增的值,就把這個(gè)輕量級(jí)鎖釋放了,而不需要等待整個(gè)插入語(yǔ)句執(zhí)行完后才釋放鎖。

InnoDB 存儲(chǔ)引擎提供了個(gè) innodb_autoinc_lock_mode 的系統(tǒng)變量,是用來(lái)控制選擇用 AUTO-INC 鎖,還是輕量級(jí)的鎖。

當(dāng) innodb_autoinc_lock_mode = 0,就采用 AUTO-INC 鎖,語(yǔ)句執(zhí)行結(jié)束后才釋放鎖;

當(dāng) innodb_autoinc_lock_mode = 2,就采用輕量級(jí)鎖,申請(qǐng)自增主鍵后就釋放鎖,并不需要等語(yǔ)句執(zhí)行后才釋放。

當(dāng) innodb_autoinc_lock_mode = 1:

普通 insert 語(yǔ)句,自增鎖在申請(qǐng)之后就馬上釋放;

類(lèi)似 insert … select 這樣的批量插入數(shù)據(jù)的語(yǔ)句,自增鎖還是要等語(yǔ)句結(jié)束后才被釋放;

當(dāng) innodb_autoinc_lock_mode = 2 是性能最高的方式,但是當(dāng)搭配 binlog 的日志格式是 statement 一起使用的時(shí)候,在「主從復(fù)制的場(chǎng)景」中會(huì)發(fā)生數(shù)據(jù)不一致的問(wèn)題

舉個(gè)例子,考慮下面場(chǎng)景:

3fc7e9c0-528a-11ed-a3b6-dac502259ad0.png

session A 往表 t 中插入了 4 行數(shù)據(jù),然后創(chuàng)建了一個(gè)相同結(jié)構(gòu)的表 t2,然后兩個(gè) session 同時(shí)執(zhí)行向表 t2 中插入數(shù)據(jù)。

如果 innodb_autoinc_lock_mode = 2,意味著「申請(qǐng)自增主鍵后就釋放鎖,不必等插入語(yǔ)句執(zhí)行完」。那么就可能出現(xiàn)這樣的情況:

session B 先插入了兩個(gè)記錄,(1,1,1)、(2,2,2);

然后,session A 來(lái)申請(qǐng)自增 id 得到 id=3,插入了(3,5,5);

之后,session B 繼續(xù)執(zhí)行,插入兩條記錄 (4,3,3)、 (5,4,4)。

可以看到,session B 的 insert 語(yǔ)句,生成的 id 不連續(xù)

當(dāng)「主庫(kù)」發(fā)生了這種情況,binlog 面對(duì) t2 表的更新只會(huì)記錄這兩個(gè) session 的 insert 語(yǔ)句,如果 binlog_format=statement,記錄的語(yǔ)句就是原始語(yǔ)句。記錄的順序要么先記 session A 的 insert 語(yǔ)句,要么先記 session B 的 insert 語(yǔ)句。

但不論是哪一種,這個(gè) binlog 拿去「從庫(kù)」執(zhí)行,這時(shí)從庫(kù)是按「順序」執(zhí)行語(yǔ)句的,只有當(dāng)執(zhí)行完一條 SQL 語(yǔ)句后,才會(huì)執(zhí)行下一條 SQL。因此,在從庫(kù)上「不會(huì)」發(fā)生像主庫(kù)那樣兩個(gè) session 「同時(shí)」執(zhí)行向表 t2 中插入數(shù)據(jù)的場(chǎng)景。所以,在備庫(kù)上執(zhí)行了 session B 的 insert 語(yǔ)句,生成的結(jié)果里面,id 都是連續(xù)的。這時(shí),主從庫(kù)就發(fā)生了數(shù)據(jù)不一致。

要解決這問(wèn)題,binlog 日志格式要設(shè)置為 row,這樣在 binlog 里面記錄的是主庫(kù)分配的自增值,到備庫(kù)執(zhí)行的時(shí)候,主庫(kù)的自增值是什么,從庫(kù)的自增值就是什么。

所以,當(dāng) innodb_autoinc_lock_mode = 2 時(shí),并且 binlog_format = row,既能提升并發(fā)性,又不會(huì)出現(xiàn)數(shù)據(jù)一致性問(wèn)題

行級(jí)鎖

InnoDB 引擎是支持行級(jí)鎖的,而 MyISAM 引擎并不支持行級(jí)鎖。

前面也提到,普通的 select 語(yǔ)句是不會(huì)對(duì)記錄加鎖的,因?yàn)樗鼘儆诳煺兆x。如果要在查詢(xún)時(shí)對(duì)記錄加行鎖,可以使用下面這兩個(gè)方式,這種查詢(xún)會(huì)加鎖的語(yǔ)句稱(chēng)為鎖定讀。

//對(duì)讀取的記錄加共享鎖
select...lockinsharemode;

//對(duì)讀取的記錄加獨(dú)占鎖
select...forupdate;

上面這兩條語(yǔ)句必須在一個(gè)事務(wù)中,因?yàn)楫?dāng)事務(wù)提交了,鎖就會(huì)被釋放,所以在使用這兩條語(yǔ)句的時(shí)候,要加上 begin、start transaction 或者 set autocommit = 0。

共享鎖(S鎖)滿(mǎn)足讀讀共享,讀寫(xiě)互斥。獨(dú)占鎖(X鎖)滿(mǎn)足寫(xiě)寫(xiě)互斥、讀寫(xiě)互斥。

4018d538-528a-11ed-a3b6-dac502259ad0.png

行級(jí)鎖的類(lèi)型主要有三類(lèi):

Record Lock,記錄鎖,也就是僅僅把一條記錄鎖上;

Gap Lock,間隙鎖,鎖定一個(gè)范圍,但是不包含記錄本身;

Next-Key Lock:Record Lock + Gap Lock 的組合,鎖定一個(gè)范圍,并且鎖定記錄本身。

Record Lock

Record Lock 稱(chēng)為記錄鎖,鎖住的是一條記錄。而且記錄鎖是有 S 鎖和 X 鎖之分的:

當(dāng)一個(gè)事務(wù)對(duì)一條記錄加了 S 型記錄鎖后,其他事務(wù)也可以繼續(xù)對(duì)該記錄加 S 型記錄鎖(S 型與 S 鎖兼容),但是不可以對(duì)該記錄加 X 型記錄鎖(S 型與 X 鎖不兼容);

當(dāng)一個(gè)事務(wù)對(duì)一條記錄加了 X 型記錄鎖后,其他事務(wù)既不可以對(duì)該記錄加 S 型記錄鎖(S 型與 X 鎖不兼容),也不可以對(duì)該記錄加 X 型記錄鎖(X 型與 X 鎖不兼容)。

舉個(gè)例子,當(dāng)一個(gè)事務(wù)執(zhí)行了下面這條語(yǔ)句:

mysql>begin;
mysql>select*fromt_testwhereid=1forupdate;

就是對(duì) t_test 表中主鍵 id 為 1 的這條記錄加上 X 型的記錄鎖,這樣其他事務(wù)就無(wú)法對(duì)這條記錄進(jìn)行修改了。

403eca5e-528a-11ed-a3b6-dac502259ad0.png

當(dāng)事務(wù)執(zhí)行 commit 后,事務(wù)過(guò)程中生成的鎖都會(huì)被釋放。

Gap Lock

Gap Lock 稱(chēng)為間隙鎖,只存在于可重復(fù)讀隔離級(jí)別,目的是為了解決可重復(fù)讀隔離級(jí)別下幻讀的現(xiàn)象。

假設(shè),表中有一個(gè)范圍 id 為(3,5)間隙鎖,那么其他事務(wù)就無(wú)法插入 id = 4 這條記錄了,這樣就有效的防止幻讀現(xiàn)象的發(fā)生。

40587b66-528a-11ed-a3b6-dac502259ad0.png

間隙鎖雖然存在 X 型間隙鎖和 S 型間隙鎖,但是并沒(méi)有什么區(qū)別,間隙鎖之間是兼容的,即兩個(gè)事務(wù)可以同時(shí)持有包含共同間隙范圍的間隙鎖,并不存在互斥關(guān)系,因?yàn)殚g隙鎖的目的是防止插入幻影記錄而提出的。

Next-Key Lock

Next-Key Lock 稱(chēng)為臨鍵鎖,是 Record Lock + Gap Lock 的組合,鎖定一個(gè)范圍,并且鎖定記錄本身。

假設(shè),表中有一個(gè)范圍 id 為(3,5] 的 next-key lock,那么其他事務(wù)即不能插入 id = 4 記錄,也不能修改 id = 5 這條記錄。

4076cd0a-528a-11ed-a3b6-dac502259ad0.png

所以,next-key lock 即能保護(hù)該記錄,又能阻止其他事務(wù)將新紀(jì)錄插入到被保護(hù)記錄前面的間隙中。

next-key lock 是包含間隙鎖+記錄鎖的,如果一個(gè)事務(wù)獲取了 X 型的 next-key lock,那么另外一個(gè)事務(wù)在獲取相同范圍的 X 型的 next-key lock 時(shí),是會(huì)被阻塞的。

比如,一個(gè)事務(wù)持有了范圍為 (1, 10] 的 X 型的 next-key lock,那么另外一個(gè)事務(wù)在獲取相同范圍的 X 型的 next-key lock 時(shí),就會(huì)被阻塞。

雖然相同范圍的間隙鎖是多個(gè)事務(wù)相互兼容的,但對(duì)于記錄鎖,我們是要考慮 X 型與 S 型關(guān)系,X 型的記錄鎖與 X 型的記錄鎖是沖突的。

插入意向鎖

一個(gè)事務(wù)在插入一條記錄的時(shí)候,需要判斷插入位置是否已被其他事務(wù)加了間隙鎖(next-key lock 也包含間隙鎖)。

如果有的話(huà),插入操作就會(huì)發(fā)生阻塞,直到擁有間隙鎖的那個(gè)事務(wù)提交為止(釋放間隙鎖的時(shí)刻),在此期間會(huì)生成一個(gè)插入意向鎖,表明有事務(wù)想在某個(gè)區(qū)間插入新記錄,但是現(xiàn)在處于等待狀態(tài)。

舉個(gè)例子,假設(shè)事務(wù) A 已經(jīng)對(duì)表加了一個(gè)范圍 id 為(3,5)間隙鎖。

40587b66-528a-11ed-a3b6-dac502259ad0.png

當(dāng)事務(wù) A 還沒(méi)提交的時(shí)候,事務(wù) B 向該表插入一條 id = 4 的新記錄,這時(shí)會(huì)判斷到插入的位置已經(jīng)被事務(wù) A 加了間隙鎖,于是事物 B 會(huì)生成一個(gè)插入意向鎖,然后將鎖的狀態(tài)設(shè)置為等待狀態(tài)(PS:MySQL 加鎖時(shí),是先生成鎖結(jié)構(gòu),然后設(shè)置鎖的狀態(tài),如果鎖狀態(tài)是等待狀態(tài),并不是意味著事務(wù)成功獲取到了鎖,只有當(dāng)鎖狀態(tài)為正常狀態(tài)時(shí),才代表事務(wù)成功獲取到了鎖),此時(shí)事務(wù) B 就會(huì)發(fā)生阻塞,直到事務(wù) A 提交了事務(wù)。

插入意向鎖名字雖然有意向鎖,但是它并不是意向鎖,它是一種特殊的間隙鎖,屬于行級(jí)別鎖

如果說(shuō)間隙鎖鎖住的是一個(gè)區(qū)間,那么「插入意向鎖」鎖住的就是一個(gè)點(diǎn)。因而從這個(gè)角度來(lái)說(shuō),插入意向鎖確實(shí)是一種特殊的間隙鎖。

插入意向鎖與間隙鎖的另一個(gè)非常重要的差別是:盡管「插入意向鎖」也屬于間隙鎖,但兩個(gè)事務(wù)卻不能在同一時(shí)間內(nèi),一個(gè)擁有間隙鎖,另一個(gè)擁有該間隙區(qū)間內(nèi)的插入意向鎖(當(dāng)然,插入意向鎖如果不在間隙鎖區(qū)間內(nèi)則是可以的)。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    4085

    瀏覽量

    68569
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    931

    瀏覽量

    29775
  • MVCC
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    1617

原文標(biāo)題:MySQL 全局鎖、表級(jí)鎖、行級(jí)鎖,你搞清楚了嗎?

文章出處:【微信號(hào):小林coding,微信公眾號(hào):小林coding】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于MySQL機(jī)制

    在數(shù)據(jù)庫(kù)系統(tǒng)中,為了保證數(shù)據(jù)的一致性和并發(fā)控制,機(jī)制發(fā)揮著至關(guān)重要的作用。尤其在關(guān)系型數(shù)據(jù)庫(kù)MySQL中,其獨(dú)特的機(jī)制設(shè)計(jì)更是贏得了許多開(kāi)發(fā)者的喜愛(ài)。 本文將詳細(xì)探討MySQL
    的頭像 發(fā)表于 09-30 11:16 ?1631次閱讀

    labview調(diào)用mysql數(shù)據(jù)庫(kù)問(wèn)題????

    labview調(diào)用mysql數(shù)據(jù)庫(kù),請(qǐng)問(wèn)labview打包成exe安裝檔,怎么把mysql數(shù)據(jù)庫(kù)打包進(jìn)來(lái),是mysql數(shù)據(jù)庫(kù),不是其他的啊?求高手
    發(fā)表于 05-19 16:17

    InnoDB的特點(diǎn)和狀態(tài)查詢(xún)

    MySQL探秘(五)InnoDB的類(lèi)型和狀態(tài)查詢(xún)
    發(fā)表于 08-07 11:45

    MySQL存儲(chǔ)引擎簡(jiǎn)析

    MySQL存儲(chǔ)引擎InnoDB??InnoDB 的存儲(chǔ)文件兩個(gè),后綴名分別是.frm和.idb,其中.frm是表的定義文件,而.idb是數(shù)據(jù)文件。InnoDB 中存在表和行,不過(guò)
    發(fā)表于 09-06 06:07

    》/《無(wú)》/《簽約》/《解鎖》/《越獄》/《激活》專(zhuān)

    》/《無(wú)》/《簽約》/《解鎖》/《越獄》/《激活》專(zhuān)業(yè)技術(shù)詞解析 在討論區(qū)里,大家看到:《版》,《無(wú)
    發(fā)表于 02-03 11:05 ?1212次閱讀

    最有用的mysql問(wèn)答

    、壓縮、空間函數(shù)等,但是不支持事務(wù)和行級(jí),所以一般用于大量查詢(xún)少量插入的場(chǎng)景來(lái)使用,而且myisam不支持外鍵,并且索引和數(shù)據(jù)是分開(kāi)存儲(chǔ)的。 innodb是基于聚簇索引建立的,和myisam相反它支持事務(wù)、外鍵,并且通過(guò)MVCC來(lái)支持高并發(fā),索引和數(shù)據(jù)存儲(chǔ)在一起。 2
    的頭像 發(fā)表于 09-30 17:43 ?2373次閱讀
    最有用的<b class='flag-5'>mysql</b>問(wèn)答

    MySQL索引的使用問(wèn)題

    一、前言 在MySQL中進(jìn)行SQL優(yōu)化的時(shí)候,經(jīng)常會(huì)在一些情況下,對(duì)MySQL能否利用索引一些迷惑。譬如:1、MySQL 在遇到范圍查詢(xún)條件的時(shí)候就停止匹配了,那么到底是哪些范圍條件
    的頭像 發(fā)表于 01-06 16:13 ?2265次閱讀

    MySQL中的高級(jí)內(nèi)容詳解

    之前兩篇文章帶你了解了 MySQL 的基礎(chǔ)語(yǔ)法和 MySQL 的進(jìn)階內(nèi)容,那么這篇文章我們來(lái)了解一下 MySQL 中的高級(jí)內(nèi)容。 其他文章: 138 張圖帶你 MySQL 入門(mén) 47
    的頭像 發(fā)表于 03-11 16:55 ?2912次閱讀
    <b class='flag-5'>MySQL</b>中的高級(jí)內(nèi)容詳解

    數(shù)據(jù)庫(kù)的機(jī)制真正的原理

    MySQL數(shù)據(jù)庫(kù)中,為了解決并發(fā)問(wèn)題,引入了很多的機(jī)制,很多時(shí)候,數(shù)據(jù)庫(kù)的是在有數(shù)據(jù)庫(kù)操作的過(guò)程中自動(dòng)添加的。所以,這就導(dǎo)致很多程序員經(jīng)常會(huì)忽略數(shù)據(jù)庫(kù)的機(jī)制的真正的原理。比如,
    的頭像 發(fā)表于 11-12 09:33 ?3051次閱讀

    智能真的那么好嗎,智能的優(yōu)勢(shì)是什么

    為什么要換智能、智能真的那么好嗎?相信一部分的人會(huì)有這樣子的疑問(wèn),但是我想說(shuō)的是,就算你不買(mǎi),但也不要否定智能的好!!
    的頭像 發(fā)表于 06-29 17:43 ?3522次閱讀

    MySQL是怎么加行級(jí)的?什么規(guī)則?

    是不是很多人都對(duì) MySQL 加行級(jí)的規(guī)則搞的迷迷糊糊,對(duì)記錄一會(huì)加的是 next-key ,一會(huì)加是間隙,一會(huì)又是記錄。
    的頭像 發(fā)表于 11-17 09:28 ?1543次閱讀

    一文徹底搞懂MySQL究竟的啥1

    MySQL系列文章已經(jīng)鴿了挺久了,最近趕緊擠了擠時(shí)間,和大家聊一聊MySQL。 只要學(xué)計(jì)算機(jī),「``」永遠(yuǎn)是一個(gè)繞不過(guò)的話(huà)題。
    的頭像 發(fā)表于 03-03 10:12 ?1134次閱讀
    一文徹底搞懂<b class='flag-5'>MySQL</b><b class='flag-5'>鎖</b>究竟<b class='flag-5'>鎖</b>的啥1

    一文徹底搞懂MySQL究竟的啥2

    MySQL系列文章已經(jīng)鴿了挺久了,最近趕緊擠了擠時(shí)間,和大家聊一聊MySQL。 只要學(xué)計(jì)算機(jī),「``」永遠(yuǎn)是一個(gè)繞不過(guò)的話(huà)題。
    的頭像 發(fā)表于 03-03 10:13 ?1083次閱讀
    一文徹底搞懂<b class='flag-5'>MySQL</b><b class='flag-5'>鎖</b>究竟<b class='flag-5'>鎖</b>的啥2

    為什么MySQL備份很重要?MySQL備份類(lèi)型哪些?

    MySQL 備份和恢復(fù)策略,它們是任何應(yīng)用程序的基石。對(duì)應(yīng)您的特定場(chǎng)景,多個(gè)選項(xiàng)可供選擇,每個(gè)選項(xiàng)都要求我們考慮相關(guān)問(wèn)題以做出明智的決策。
    的頭像 發(fā)表于 11-14 10:20 ?1407次閱讀

    阿里二面:了解MySQL事務(wù)底層原理嗎

    MySQL 是如何來(lái)解決臟寫(xiě)這種問(wèn)題的?沒(méi)錯(cuò),就是。MySQL 在開(kāi)啟一個(gè)事務(wù)的時(shí)候,他會(huì)將某條記錄和事務(wù)做一個(gè)綁定。這個(gè)其實(shí)和 JVM 是類(lèi)似的。
    的頭像 發(fā)表于 01-18 16:34 ?932次閱讀
    阿里二面:了解<b class='flag-5'>MySQL</b>事務(wù)底層原理嗎
    贵港市| 宁夏| 靖宇县| 登封市| 桃源县| 剑阁县| 梧州市| 东丽区| 洛隆县| 漠河县| 蓝田县| 富锦市| 邢台市| 银川市| 佛坪县| 旅游| 临江市| 大荔县| 无极县| 巴彦淖尔市| 阳江市| 华蓥市| 中宁县| 英吉沙县| 海口市| 繁峙县| 遵义市| 开江县| 长垣县| 洛扎县| 武穴市| 安阳市| 台南县| 九寨沟县| 唐河县| 兰考县| 溆浦县| 丰县| 兰州市| 建阳市| 尚义县|