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

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

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

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

jf_78858299 ? 來源:蟬沐風(fēng)的碼場 ? 作者:蟬沐風(fēng) ? 2023-03-03 10:12 ? 次閱讀

MySQL鎖系列文章已經(jīng)鴿了挺久了,最近趕緊擠了擠時間,和大家聊一聊MySQL的鎖。

只要學(xué)計算機,「」永遠(yuǎn)是一個繞不過的話題。MySQL鎖也是一樣。

一句話解釋MySQL鎖:

MySQL鎖是解決資源競爭的一種方案。

短短一句話卻包含了3點值得我們注意的事情:

  1. 對什么資源進(jìn)行競爭?
  2. 競爭的方式(或者說情形)有哪些?
  3. 鎖是如何解決競爭的?

這篇文章開始帶你循序漸進(jìn)地理解這幾個問題。

1. 資源的競爭方式

MySQL對資源的操作無非就是 兩種方式,但是由于事務(wù)并發(fā)執(zhí)行的存在,因此對同一資源的并發(fā)訪問存在3種形式:

  • 讀—讀:并發(fā)事務(wù)同時讀取相同資源。由于讀操作不會改變資源本身,因此 這種情況下并不存在并發(fā)安全性問題
  • 讀—寫/寫—讀:一個事務(wù)對資源進(jìn)行讀操作,另一個事務(wù)對資源進(jìn)行寫操作。
  • 寫—寫:并發(fā)事務(wù)同時對同一個資源進(jìn)行寫操作。

2. 讀—寫/寫—讀下的問題

假設(shè)一種情形,一個事務(wù)先對某個資源進(jìn)行讀操作,然后另一個事務(wù)再對該資源進(jìn)行寫操作,如果兩個事務(wù)到此為止,必然不會導(dǎo)致并發(fā)問題。

可是事務(wù)這種東西,一般情況下就是包含有很多個子操作啊。

2.1. 幻讀

想象一下啊,假設(shè)事務(wù)T1T2并發(fā)執(zhí)行,T1先查找了所有name為「王剛蛋」的用戶信息,此時發(fā)現(xiàn)擁有這個硬漢名字的用戶只有一個。然后T2插入了一個同樣叫做「王剛蛋」的用戶的信息,并且提交了。

圖片

幻讀

圖片

2.2. 不可重復(fù)讀

再來,同樣是T1T2兩個事務(wù),T1通過id = 1查詢到了一條數(shù)據(jù),然后T2緊接著UPDATEDELETE也可以)了該條記錄,不同的是,T2緊接著通過COMMIT提交了事務(wù)。

圖片

此時,T1再次執(zhí)行相同的查詢操作,會發(fā)現(xiàn)數(shù)據(jù)發(fā)生了變化,name字段由「王剛蛋」變成了「蟬沐風(fēng)」。

如果一個事務(wù)讀到了另一個已提交事務(wù)修改過的(或者是刪除的)數(shù)據(jù),而導(dǎo)致了前后兩次讀取的數(shù)據(jù)不一致的情況,這種事務(wù)并發(fā)問題叫做 不可重復(fù)讀 。

2.3. 臟讀

事情還沒結(jié)束,假設(shè)T1T2都要訪問user_innodb表中id1的數(shù)據(jù),不同的是T1先讀取數(shù)據(jù),緊接著T2修改了數(shù)據(jù)的name字段,需要注意的是,T2并沒有提交!

圖片

此時,T1再次執(zhí)行相同的查詢操作,會發(fā)現(xiàn)數(shù)據(jù)發(fā)生了變化,name字段由「王剛蛋」變成了「蟬沐風(fēng)」。

如果一個事務(wù)讀到了另一個未提交事務(wù)修改過的數(shù)據(jù),而導(dǎo)致了前后兩次讀取的數(shù)據(jù)不一致的情況,這種事務(wù)并發(fā)問題叫做 臟讀

2.4. 鎖與MVCC的關(guān)系

總結(jié)一下:我們在讀—寫,寫—讀的情況下會遇到3種讀不一致性的問題,臟讀、不可重復(fù)讀以及幻讀。

那寫—寫呢?很顯然,在不做任何措施的情況下,并發(fā)會出現(xiàn)更大的問題。那該怎么辦呢?

一切的并發(fā)問題都可以通過串行化解決,但是串行化效率太低了!

再優(yōu)化一下,一切并發(fā)問題都可以通過加鎖來解決,這種方案我們稱為 基于鎖的并發(fā)控制Lock Bases Concurrency Control , LBCC )!但是在讀多寫少的環(huán)境下,客戶端連讀取幾條記錄都需要排隊,效率還是太低了!

因此,MySQL的設(shè)計者為事務(wù)之間的隔離性提供了不同的級別,使得開發(fā)者可以根據(jù)自己的業(yè)務(wù)場景設(shè)置不同的隔離級別,來解決(或者部分解決)讀—寫/寫—讀下的讀一致性問題,而不是一上來就加鎖。

這種機制叫做MVCC,如果你對這個概念不是很了解,我建議你暫停一下,讀一下我的事務(wù)的隔離性與MVCC這篇文章,寫得賊好?。。ㄗ再u自夸一下)

那有了MVCC是不是在讀—寫/寫—讀的情況下就不需要鎖了呢?那也不是。

MVCC解決的是讀—寫/寫—讀中“ 比較純粹的讀 ”遇到的一致性問題,原諒我,這是我自己編的詞兒。那什么是不純粹的?拿存款業(yè)務(wù)舉個例子。

假設(shè)陀螺要存一筆錢,系統(tǒng)需要先把陀螺的余額讀出來,然后在余額的基礎(chǔ)上加上本次存款的金額,最后再寫入到數(shù)據(jù)庫中。在將余額讀出來之后,如果不想讓其他事務(wù)繼續(xù)訪問該余額,直到整個存款事務(wù)完成之后,其他事務(wù)才可以對該余額繼續(xù)進(jìn)行操作,這種情況下就必須為余額的讀取操作添加鎖。

再總結(jié)一下: MVCC是MySQL默認(rèn)的解決讀—寫/寫—讀下一致性問題的方式,不需要加鎖。而鎖是實現(xiàn)一致性的最終兜底方案,在某些特殊場景下,鎖的使用不可避免 。

說得更準(zhǔn)確一點,MVCC是MySQL在READ COMMITTED、REPEATABLE READ這兩種隔離級別之下執(zhí)行普通SELECT操作時默認(rèn)解決一致性問題的方式。

具體為什么只是這兩種隔離級別,建議你看看事務(wù)的隔離性與MVCC。

2.5. 鎖與事務(wù)的關(guān)系

事務(wù)是多個操作的集合,比如我們可以把「把大象裝冰箱」這件事情作為一個事務(wù)。

圖片

事務(wù)有A(原子性)、C(一致性)、I(隔離性)、D(持久性)4大特性,而鎖就是實現(xiàn)隔離性的其中一種方案(比如還有MVCC等方案)。

事務(wù)的隔離性針對不同場景需求又實現(xiàn)了不同的隔離級別,不同的隔離級別下,事務(wù)使用鎖的方式又會有所不同。舉個例子。

READ COMMITTED、REPEATABLE READ這兩種隔離級別之下,SELECT操作是不需要加鎖的,直接使用MVCC機制即可滿足當(dāng)前隔離級別的需求。但是在SERIALIZABLE隔離級別,并且在禁用自動提交時(autocommit=0),MySQL會將普通的SELECT語句轉(zhuǎn)化為SELECT ... LOCK IN SHARE MODE這樣的加鎖語句,如果你看不懂這句話也沒關(guān)系,你只需要知道MySQL自動加鎖了就行,更詳細(xì)的下文再說。

另外,一個事務(wù)可能會加很多個鎖,但是某個鎖一定只屬于一個事務(wù)。這就好比一個管理員可以管理多個保險柜,一個保險柜一定只被一個管理員管理。

3. 寫—寫情況

寫—寫的情況下肯定要加鎖的了,所以接下來終于要聊一聊鎖了。

我們首先研究一下鎖住的東西的大小,也就是鎖的粒度。

4. 鎖的粒度

舉一個非常應(yīng)景的例子。疫情防控的時候,是封鎖整個小區(qū)還是封鎖某棟樓的某個單元,這完全是兩種概念。

對應(yīng)到MySQL鎖的粒度,那就是表鎖行鎖。

很容易想到,封鎖小區(qū)的行為遠(yuǎn)比封鎖某棟樓某單元的行為粗曠,因此,

從鎖定粒度上來看,表鎖 > 行鎖

直接堵住小區(qū)的門口要比進(jìn)入小區(qū)找到具體某棟樓的某個單元要快不少,因此,

從加鎖效率上來看,表鎖 > 行鎖

直接鎖住小區(qū)大概率會影響其他樓居民的正常生活和各種社會活動的開展,而鎖住某棟樓某單元頂多影響這一個單元的居民的生活,因此,

從沖突概率來看,表鎖 > 行鎖

從并發(fā)性能來看,表鎖 < 行鎖

MySQL支持很多存儲引擎,而不同的存儲引擎對鎖的支持也不盡相同。對于MyISAM、MERGE、MEMORY這些存儲引擎而言,只支持表鎖;而InnoDB存儲引擎既支持表鎖也支持行鎖,下文討論的所有內(nèi)容均針對InnoDB存儲引擎。

說完鎖的粒度,還有一件事情需要我們仔細(xì)考慮一下。上文說過,READ COMMITTED、REPEATABLE READ這兩種隔離級別之下,SELECT操作默認(rèn)采用MVCC機制就可以了,壓根兒不需要加鎖,那么問題來了,萬一我就是想加鎖呢?

你可能會說,“簡單啊,那就加鎖!把數(shù)據(jù)鎖死!除了我誰也別動!”

很好,但是對于大部分讀—讀而言,由于不會出現(xiàn)讀一致性問題,所以不讓其他事務(wù)進(jìn)行讀操作并不合理。

你可能又說,“那行吧,那就讓讀操作加鎖的時候允許其他事務(wù)對鎖住的數(shù)據(jù)進(jìn)行讀操作,但是不允許寫操作?!?/p>

嗯,想得確實更細(xì)致了一些。但是再想想我上文中舉過的陀螺存錢的例子,有時候SELECT操作需要獨占數(shù)據(jù),其他事務(wù)既不能讀,更不能寫。

我們把這種共享排他的性質(zhì)稱為鎖的基本模式。

5. 鎖的基本模式

5.1. 共享鎖

共享鎖(Shared Lock),簡稱S鎖,可以同時被多個事務(wù)共享,也就是說,如果一個事務(wù)給某個數(shù)據(jù)資源添加了S鎖,其他事務(wù)也被允許獲取該數(shù)據(jù)資源的S鎖。

由于S鎖通常被用于讀取數(shù)據(jù),因此也被稱為 讀鎖

那怎么給數(shù)據(jù)添加S鎖呢?

我們可以用 SELECT ... LOCK IN SHARE MODE;的方式,在讀取數(shù)據(jù)之前就為數(shù)據(jù)添加一把S鎖。如果當(dāng)前事務(wù)執(zhí)行了該語句,那么會為讀取到的記錄添加S鎖,同時其他事務(wù)也可以使用SELECT ... LOCK IN SHARE MODE;方式繼續(xù)獲取這些數(shù)據(jù)的S鎖。

我們通過以下的例子驗證一下S鎖是否可以重復(fù)獲取。

圖片

5.2. 排他鎖

排他鎖(Exclusive Lock),簡稱X鎖。只要一個事務(wù)獲取了某數(shù)據(jù)資源的X鎖,其他的事務(wù)就不能再獲取該數(shù)據(jù)的X鎖和S鎖。

由于X鎖通常被用于修改數(shù)據(jù),因此也被稱為 寫鎖 。

X鎖的添加方式有兩種,

  1. 自動添加X
    我們對記錄進(jìn)行增刪改時,通常情況下會自動對其添加X鎖。
  2. 手動加鎖
    我們可以用 SELECT ... FOR UPDATE;的方式,在讀取數(shù)據(jù)之前就為數(shù)據(jù)添加一把X鎖。如果當(dāng)前事務(wù)執(zhí)行了該語句,那么會為讀取到的記錄添加X鎖,這樣既不允許其他事務(wù)獲取這些記錄的S鎖,也不允許獲取這些記錄的X鎖。

我們用下面的例子驗證一下X鎖的排他性。

圖片

通常情況下,事務(wù)提交或結(jié)束事務(wù)時,鎖會被釋放。

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

    關(guān)注

    19

    文章

    7494

    瀏覽量

    87981
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    811

    瀏覽量

    26580
  • MVCC
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    1470
收藏 人收藏

    評論

    相關(guān)推薦

    基于MySQL機制

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

    redis分布式場景實現(xiàn)

    今天帶大家深入剖析下Redis分布式,徹底搞懂它。 場景 既然要搞懂Redis分布式,那肯
    的頭像 發(fā)表于 09-25 17:09 ?722次閱讀

    請問DSPflash死后,RAM還可以用嗎,還是這塊芯片就徹底廢了?

    本帖最后由 只耳朵怪 于 2018-6-13 16:47 編輯 請問DSPflash死后,RAM還可以用嗎,還是這塊芯片就徹底廢了?
    發(fā)表于 06-13 04:19

    InnoDB的特點和狀態(tài)查詢

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

    讀懂eMMC究竟?

    eMMC究竟?eMMC長什么樣?eMMC用在哪?主要是干嘛用的?eMMC究竟是如何工作的呢?
    發(fā)表于 06-18 06:04

    360為什么會入局智能市場

    很難界定智能究竟屬于哪個行業(yè)?智能是五金門鎖行業(yè)、安防行業(yè)、家居行業(yè)和產(chǎn)業(yè)互聯(lián)網(wǎng)行業(yè)的交匯產(chǎn)物。硬件是基礎(chǔ),安防及家居是應(yīng)用,網(wǎng)絡(luò)是消費渠道及用戶交互界面,物聯(lián)網(wǎng)讓智能
    發(fā)表于 11-05 15:21 ?1498次閱讀

    詳細(xì)介紹MySQL InnoDB存儲引擎各種不同類型的

    T1執(zhí)行時,需要獲取i=1的行的X(不需要獲取t1表的意向了);T2執(zhí)行時,需要獲取t1表的
    的頭像 發(fā)表于 02-20 11:12 ?7648次閱讀
    詳細(xì)介紹<b class='flag-5'>MySQL</b> InnoDB存儲引擎各種不同類型的<b class='flag-5'>鎖</b>

    徹底搞懂PID到底是

    先來徹底搞懂PID到底是? PID,就是比例(proportional)、積分(integral)、微分(differential),是種很常見的控制算法。在工程實際中,應(yīng)用最為廣
    的頭像 發(fā)表于 11-13 18:21 ?2.5w次閱讀

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

    問候選人,你知道MySQL Innodb的,到底的是什么嗎?關(guān)于這個問題的回答,聽到過很多種,但是很少有人可以把他回答的很完美。因為想要回答好這個問題,需要對數(shù)據(jù)庫的隔離級別、索引等都有
    的頭像 發(fā)表于 11-12 09:33 ?2273次閱讀

    說說MySQL有哪些

    增加自增為 innodb_autoinc_lock_mode = 2 模式時,為什么主從環(huán)境會有不安全問題的說明
    的頭像 發(fā)表于 10-24 10:15 ?872次閱讀

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

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

    徹底搞懂MySQL究竟2

    MySQL系列文章已經(jīng)鴿了挺久了,最近趕緊擠了擠時間,和大家聊MySQL。 只要學(xué)計算機,「`
    的頭像 發(fā)表于 03-03 10:13 ?440次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>徹底</b><b class='flag-5'>搞懂</b><b class='flag-5'>MySQL</b><b class='flag-5'>鎖</b><b class='flag-5'>究竟</b><b class='flag-5'>鎖</b>的<b class='flag-5'>啥</b>2

    Linux互斥的作用 互斥是什么

    1、互斥 互斥(mutex),在訪問共享資源之前對互斥進(jìn)行上鎖,在訪問完成后釋放互斥(解鎖);對互斥
    的頭像 發(fā)表于 07-21 11:13 ?946次閱讀

    自旋和互斥的區(qū)別有哪些

    自旋 自旋與互斥很相似,在訪問共享資源之前對自旋進(jìn)行上鎖,在訪問完成后釋放自旋(解鎖);事實上,從實現(xiàn)方式上來說,互斥
    的頭像 發(fā)表于 07-21 11:19 ?9500次閱讀

    互斥和自旋的實現(xiàn)原理

    互斥和自旋是操作系統(tǒng)中常用的同步機制,用于控制對共享資源的訪問,以避免多個線程或進(jìn)程同時訪問同資源,從而引發(fā)數(shù)據(jù)不致或競爭條件等問題。 互斥
    的頭像 發(fā)表于 07-10 10:07 ?495次閱讀