MySQL使用表鎖和行鎖的場(chǎng)景詳解
前言
MySQL Innodb 的鎖可以說(shuō)是執(zhí)行引擎的并發(fā)基礎(chǔ)了,有了鎖才能保證數(shù)據(jù)的一致性。眾所周知,我們都知道 Innodb 有全局鎖、表級(jí)鎖、行級(jí)鎖三種,但你知道什么時(shí)候會(huì)用表鎖,什么時(shí)候會(huì)用行鎖嗎?
雖然對(duì) MySQL 的知識(shí)點(diǎn)挺熟悉的,但一開(kāi)始看到這個(gè)問(wèn)題,樹(shù)哥也是有點(diǎn)懵,我還真沒(méi)從這個(gè)角度去思考過(guò)。大家可以暫時(shí) 1 分鐘思考下答案,后面我將帶大家弄清楚這個(gè)問(wèn)題。
對(duì)于這個(gè)問(wèn)題,我只能粗略地想起一些片段,例如:
- 對(duì)于表級(jí)鎖而言,當(dāng)執(zhí)行 DDL 語(yǔ)句去修改表結(jié)構(gòu)時(shí),會(huì)使用表級(jí)鎖。
- 對(duì)于行級(jí)鎖而言,一般情況下都會(huì)默認(rèn)使用行級(jí)鎖,貌似是需要有索引匹配到才行。
上面就是我粗略想到的答案,不知道大家思考的答案是否和我一樣呢?下面就讓我?guī)е蠹襾?lái)溫習(xí)下 MySQL 的鎖吧!
文章思維導(dǎo)圖
對(duì)于數(shù)據(jù)庫(kù)而言,其鎖范圍可以分為:
- 全局鎖
- 表級(jí)鎖
- 行級(jí)鎖
全局鎖
全局鎖就是對(duì)整個(gè)數(shù)據(jù)庫(kù)實(shí)例加鎖。 MySQL 提供了一個(gè)加全局讀鎖的方法,命令是 Flush tables with read lock (FTWRL)。當(dāng)你需要讓整個(gè)庫(kù)處于只讀狀態(tài)的時(shí)候,可以使用這個(gè)命令,之后其他線程的以下語(yǔ)句會(huì)被阻塞:數(shù)據(jù)更新語(yǔ)句(數(shù)據(jù)的增刪改)、數(shù)據(jù)定義語(yǔ)句(包括建表、修改表結(jié)構(gòu)等)和更新類(lèi)事務(wù)的提交語(yǔ)句。你可以理解為,全局鎖基本上把數(shù)據(jù)所所有的變更語(yǔ)句都鎖住了。
全局鎖的典型場(chǎng)景應(yīng)用場(chǎng)景是全庫(kù)邏輯備份,也就是把整個(gè)庫(kù)每個(gè)表都 select 出來(lái)存起來(lái)。上面說(shuō)到全局鎖會(huì)鎖住所有變更語(yǔ)句,但這只是對(duì)于 MyISAM 存儲(chǔ)引擎而言的。對(duì)于 Innodb 而言,其可以利用 MVCC 實(shí)現(xiàn)數(shù)據(jù)的一致性視圖,從而不需要鎖整個(gè)庫(kù)就可以實(shí)現(xiàn)全庫(kù)的數(shù)據(jù)備份。
表級(jí)鎖
表級(jí)鎖可以分為:表鎖、元數(shù)據(jù)鎖、意向鎖三種。
表鎖
表鎖,顧名思義就是對(duì)某個(gè)表加鎖。
那什么時(shí)候會(huì)使用表鎖呢?
一般情況是對(duì)應(yīng)的存儲(chǔ)引擎沒(méi)有行級(jí)鎖(例如:MyIASM),或者是對(duì)應(yīng)的 SQL 語(yǔ)句沒(méi)有匹配到索引。
對(duì)于第一種情況而言,因?yàn)閷?duì)應(yīng)存儲(chǔ)引擎不支持行鎖,所以只能是使用更粗粒度的鎖來(lái)實(shí)現(xiàn),這也比較好理解。
對(duì)于第二種情況而言,如果存儲(chǔ)引擎支持行鎖,但對(duì)應(yīng)的 SQL 就沒(méi)有使用索引,那么此時(shí)也是會(huì)全表掃描,那此時(shí)也是會(huì)使用表鎖。例如下面的語(yǔ)句沒(méi)有指定查詢(xún)列,或者指定了查詢(xún)列但是并沒(méi)有用到索引,那么也是會(huì)直接鎖定整個(gè)表。
//?沒(méi)有指定查詢(xún)列 select?*?from?user; //?指定查詢(xún)列,但是沒(méi)有用到索引 select?*?from?user?where?name?=?'zhangsan';
上面說(shuō)的索引,可以說(shuō)是判斷是否會(huì)用行級(jí)鎖的關(guān)鍵。但我想到一個(gè)問(wèn)題:如果查詢(xún)或更新用到了索引,但是查詢(xún)或更新的數(shù)據(jù)特別多,占全表的 80% 甚至更多,這時(shí)候是會(huì)用表鎖,還是行鎖呢? 這是一個(gè)很有意思的問(wèn)題,感興趣的朋友自行弄個(gè)測(cè)試表驗(yàn)證一下,后續(xù)有機(jī)會(huì)我們?cè)倭牧倪@個(gè)問(wèn)題。
元數(shù)據(jù)鎖
元數(shù)據(jù),指的是我們的表結(jié)構(gòu)這些元數(shù)據(jù)。元數(shù)據(jù)鎖(Metadata Lock)自然是執(zhí)行 DDL 表結(jié)構(gòu)變更語(yǔ)句時(shí),我們對(duì)表加上的一個(gè)鎖了。
那什么時(shí)候會(huì)使用元數(shù)據(jù)鎖這個(gè)表級(jí)鎖呢?
當(dāng)我們對(duì)一個(gè)表做增刪改查操作的時(shí)候,會(huì)加上 MDL 讀鎖;當(dāng)我們要對(duì)表結(jié)構(gòu)做變更時(shí),就會(huì)加 MDL 寫(xiě)鎖。
意向鎖
意向鎖,本質(zhì)上就是空間換時(shí)間的產(chǎn)物,是為了提高行鎖效率的一個(gè)東西。
在 InnoDB 中,我們對(duì)某條記錄進(jìn)行鎖定時(shí),為了提高并發(fā)度,通常都只是鎖定這一行記錄,而不是鎖定整個(gè)表。而當(dāng)我們需要為整個(gè)表加 X 鎖的時(shí)候,我們就需要遍歷整個(gè)表的記錄,如果每條記錄都沒(méi)有被加鎖,才可以給整個(gè)表加 X 鎖。而這個(gè)遍歷過(guò)程就很費(fèi)時(shí)間,這時(shí)候就有了意向鎖的誕生。
意向鎖其實(shí)就是標(biāo)記這個(gè)表有沒(méi)有被鎖,如果有某條記錄被鎖住了,那么就必須獲取該表的意向鎖。所以當(dāng)我們需要判斷這個(gè)表的記錄有沒(méi)有被加鎖時(shí),直接判斷意向鎖就可以了,減少了遍歷的時(shí)間,提高了效率,是典型的用空間換時(shí)間的做法。
那么什么時(shí)候會(huì)用到意向鎖呢?
很簡(jiǎn)單,就是在對(duì)表中的行記錄加鎖的時(shí)候,就會(huì)用到意向鎖。
行級(jí)鎖
千呼萬(wàn)喚,終于來(lái)到了行級(jí)鎖。
要知道的是,行級(jí)鎖是存儲(chǔ)引擎級(jí)別的鎖,需要存儲(chǔ)引擎支持才有效。目前 MyISAM 存儲(chǔ)引擎不支持行級(jí)鎖,而 Innodb 存儲(chǔ)引擎則支持行級(jí)鎖。而全局鎖、表級(jí)鎖,則是 MySQL 層面就支持的鎖。
那么什么時(shí)候會(huì)使用行級(jí)鎖呢?
當(dāng)增刪改查匹配到索引時(shí),Innodb 會(huì)使用行級(jí)鎖。
如果沒(méi)有匹配不到索引,那么就會(huì)直接使用表級(jí)鎖。
總結(jié)
文章最后,我們回顧一下開(kāi)頭提出的問(wèn)題:Innodb 啥時(shí)候用表鎖,啥時(shí)候用行鎖?
表級(jí)鎖包括:表鎖、元數(shù)據(jù)鎖、意向鎖。
對(duì)于表鎖而言,當(dāng)存儲(chǔ)引擎不支持行級(jí)鎖時(shí),使用表鎖。SQL 語(yǔ)句沒(méi)有匹配到索引時(shí),使用表鎖。
對(duì)于元數(shù)據(jù)鎖而言,對(duì)表做增刪改查時(shí),會(huì)加上 MDL 讀鎖。對(duì)表結(jié)構(gòu)做變更時(shí),會(huì)加上 MDL 寫(xiě)鎖。
對(duì)于意向鎖而言,對(duì)表中的行記錄加鎖時(shí),會(huì)用到意向鎖。
而對(duì)于行級(jí)鎖而言,增刪改查匹配到索引時(shí),會(huì)使用行級(jí)鎖。
文章思維導(dǎo)圖
以上就是MySQL使用表鎖和行鎖的場(chǎng)景詳解的詳細(xì)內(nèi)容,更多關(guān)于MySQL表鎖 行鎖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySQL與Oracle的語(yǔ)法區(qū)別詳細(xì)對(duì)比
Oracle和mysql的一些簡(jiǎn)單命令對(duì)比在本文中將會(huì)涉及到很多的實(shí)例,感興趣的你不妨學(xué)習(xí)一下,就當(dāng)鞏固自己的知識(shí)了2013-03-03mysqlreport顯示Com_中change_db占用比例高的問(wèn)題的解決方法
最近公司的mysql服務(wù)器經(jīng)常出現(xiàn)阻塞狀態(tài)。動(dòng)不動(dòng)就重啟,給用戶(hù)訪問(wèn)帶來(lái)了相當(dāng)?shù)牟槐恪?/div> 2009-05-05如何解決局域網(wǎng)內(nèi)mysql數(shù)據(jù)庫(kù)連接慢
通過(guò)內(nèi)網(wǎng)連另外一臺(tái)機(jī)器的mysql服務(wù), 確發(fā)現(xiàn)速度N慢! 等了大約幾十秒才等到提示輸入密碼。非常急人,有沒(méi)有辦法可以解決局域網(wǎng)內(nèi)mysql數(shù)據(jù)庫(kù)連接慢呢?下面小編帶領(lǐng)大家來(lái)解決此問(wèn)題,感興趣的朋友一起看看吧2015-09-09rpm -ivh方式安裝mysql并修改數(shù)據(jù)存儲(chǔ)位置的實(shí)現(xiàn)
在Linux環(huán)境下進(jìn)行MySQL的安裝可以使用不同的方式,但在本文中我們將關(guān)注一種特定的方式,即通過(guò)RPM包的方式進(jìn)行安裝,本文主要介紹了rpm -ivh方式安裝mysql并修改數(shù)據(jù)存儲(chǔ)位置的實(shí)現(xiàn),感興趣的可以了解一下2023-09-09mysql查詢(xún)表里的重復(fù)數(shù)據(jù)方法
這篇文章主要介紹了mysql查詢(xún)表里的重復(fù)數(shù)據(jù)方法,需要的朋友可以參考下2017-05-05win2008 R2 WEB環(huán)境配置之MYSQL 5.6.22安裝版安裝配置方法
這篇文章主要介紹了win2008 R2 WEB環(huán)境配置之MYSQL 5.6.22安裝版安裝配置方法,需要的朋友可以參考下2016-06-06最新評(píng)論