[MySQL]四.InnoDB鎖機(jī)制(鎖的基本概念和使用)

?鎖類型:

1.MyISAM 和 Memory 存儲(chǔ)引擎使用的是表級(jí)鎖,BDB 引擎使用的是頁級(jí)鎖,也支持表級(jí)鎖。

2.InnoDB 存儲(chǔ)引擎既支持行級(jí)鎖,也支持表級(jí)鎖,默認(rèn)情況下使用行級(jí)鎖。

3.表級(jí)鎖:它是直接鎖住整個(gè)表,開銷小,加鎖速度快,鎖住顆粒大,?不會(huì)出現(xiàn)死鎖的情況,應(yīng)對(duì)并發(fā)情況極差。

4.行級(jí)鎖:它直接鎖住一條記錄,開銷大,加鎖慢,鎖住顆粒小,?發(fā)送鎖沖突概率低,適合并發(fā)情況。(重點(diǎn)敘述)

(注:行級(jí)鎖又分為共享鎖和排他鎖 悲觀鎖和樂觀鎖實(shí)際上是鎖機(jī)制抽象的描述)

5.頁級(jí)鎖:它是鎖住一個(gè)頁面,在innodb中一個(gè)頁面大小大概為16KB,它開銷介于表鎖和行鎖之間,

可能會(huì)死鎖,鎖住顆粒大小也介于表鎖和行鎖之間,并發(fā)度也介于表鎖和行鎖之間(一般很少使用)。

不同鎖影響的數(shù)據(jù)量不一樣:

? ??????????????表鎖????>????頁鎖????>????行鎖

性能(鎖對(duì)于數(shù)據(jù)的鎖住的速度):

? ? ? ? ? ?? ???表鎖? ? >? ? 頁鎖? ? >? ? 行鎖

注:表鎖雖然性能好但是并不適合并發(fā),因?yàn)槭褂昧吮礞i整張表會(huì)鎖住,其他進(jìn)程用戶會(huì)阻塞。而行鎖只會(huì)鎖住一條數(shù)據(jù)。

InnoDB行級(jí)鎖:

InnoDB有兩種類型的行級(jí)鎖,兩種內(nèi)部使用的意向鎖;

· 共享鎖(S)

· 排他鎖(X)

· 意向共享鎖(IS)

· 意向排他鎖(IX)

· 悲觀鎖:抽象概念,并不真實(shí)存在(通過加鎖來實(shí)現(xiàn)想要的效果)

· 樂觀鎖:抽象概念,并不真實(shí)存在(MVCC 不通過加鎖來實(shí)現(xiàn)想要的效果)

注:意向鎖是InnoDB存儲(chǔ)引擎自動(dòng)加的,不需要用戶干預(yù),對(duì)于普通select語句,InnoDB不會(huì)加任何鎖,對(duì)于insert,update,delete語句,InnoDB會(huì)自動(dòng)給涉及的數(shù)據(jù)加隱示排他鎖。

鎖沖突:

共享鎖:除了和排他鎖以外的鎖使用都是兼容的不會(huì)造成沖突;

排他鎖:排他鎖與任何鎖一起使用都會(huì)沖突造成鎖等待需要釋放;

共享鎖和排他鎖:(沖突)

共享鎖和排他鎖一起使用沖突示例

共享鎖和共享鎖:(兼容)

共享鎖和共享鎖一起使用兼容示例

排他鎖和排他鎖:(沖突)

排他鎖和排他鎖一起使用鎖沖突等待示例

共享鎖:只可以讀不可以寫

排他鎖:不可以讀不可以寫

注:當(dāng)使用MySQL事務(wù)的時(shí)候,其實(shí)底層是通過行級(jí)鎖來實(shí)現(xiàn)的。


鎖的使用方式:

innoDB顯示加共享鎖:select * from?table_name lock in share mode;

innoDB顯示加排他鎖:select * from?table_name for update;


死鎖:

出現(xiàn)原因:因?yàn)殒i互相沖突,導(dǎo)致了回環(huán)等待,從而造成了死鎖的出現(xiàn);?

表鎖不會(huì)出現(xiàn)死鎖的情況;

死鎖演示:

鎖回環(huán)等待造成死鎖示例一

凡是執(zhí)行insert update delete 的時(shí)候 MySQL都會(huì)默認(rèn)隱示加上排他鎖:

進(jìn)程一死鎖,優(yōu)先執(zhí)行先行事務(wù) 后執(zhí)行的事務(wù)進(jìn)行回滾并拋出異常示例二

innodb 應(yīng)對(duì)死鎖情況:

1.優(yōu)先判斷事務(wù)的大小 回滾事務(wù)小的(事務(wù)大?。翰僮鞯臄?shù)據(jù)量 影響的顆粒大小)

2.若事務(wù)大小一致的話 會(huì)優(yōu)先執(zhí)行先執(zhí)行的事務(wù) 后執(zhí)行的事務(wù)拋出死鎖異常(回滾需要手動(dòng))

innodb不具備頁鎖;

注:innodb會(huì)出現(xiàn)行鎖會(huì)轉(zhuǎn)化成表鎖的情況;


行鎖轉(zhuǎn)表鎖:

演示一:

行鎖轉(zhuǎn)表鎖示例(user表取消了主鍵和所有索引)

上圖所示:進(jìn)程一給id=1的數(shù)據(jù)加上了排他鎖,而進(jìn)程二修改的示id=2的數(shù)據(jù)但是進(jìn)程二卻出現(xiàn)了鎖等待的情況,出現(xiàn)這情況是因?yàn)閕nnodb行鎖被轉(zhuǎn)換成表鎖了。

即 :若數(shù)據(jù)表中如果沒有唯一鍵,主鍵那么行鎖就會(huì)自動(dòng)轉(zhuǎn)換成表鎖,因?yàn)閕nnodb行級(jí)鎖 是通過給索引加鎖來實(shí)現(xiàn)的。

演示二:

行鎖轉(zhuǎn)表鎖示例(user表只建立了主鍵id索引)

如上圖所示:進(jìn)程一查詢數(shù)據(jù)name = 川桑一號(hào)的時(shí)候加了排他鎖,而進(jìn)程二修改的數(shù)據(jù)是name = 川桑二號(hào) 但是卻出現(xiàn)了鎖等待。此種情況也是行鎖轉(zhuǎn)表鎖了。因?yàn)閡ser表雖然加上了id主鍵索引,但是在使用鎖查詢的時(shí)候 where條件使用的字段name并沒有索引,從而導(dǎo)致了行鎖轉(zhuǎn)換成了表鎖。所以在使用鎖的時(shí)候where條件字段應(yīng)該用建立了索引的字段防止行鎖轉(zhuǎn)表鎖。

演示三:

行鎖轉(zhuǎn)表鎖示例(user表只建立了主鍵id索引)

如上圖所示:進(jìn)程一查詢name = 川桑一號(hào)的數(shù)據(jù)并加上了共享鎖,而進(jìn)程二修改name = 川桑二號(hào)的數(shù)據(jù) 但是卻還是出現(xiàn)了鎖等待。原因同上。

(注:以上測(cè)試鎖機(jī)制示例使用的MySQL5.7.26版本)

間隙鎖:

即:鎖住一個(gè)區(qū)間范圍內(nèi)的數(shù)據(jù)防止別人寫入,默認(rèn)innodb是開啟間隙鎖的,可以通過修改配置參數(shù)關(guān)閉間隙鎖(官網(wǎng)并不推薦你這么做)

間隙鎖主要應(yīng)對(duì)的是幻讀問題(此篇不贅述幻讀問題)但是使用間隙鎖過程中容易出現(xiàn)死鎖的問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容