?鎖類型:
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)死鎖的情況;
死鎖演示:

凡是執(zhí)行insert update delete 的時(shí)候 MySQL都會(huì)默認(rè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)表鎖:
演示一:

上圖所示:進(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)的。
演示二:

如上圖所示:進(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)表鎖。
演示三:

如上圖所示:進(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)死鎖的問題。