MySQL原理學(xué)習(xí)知識匯總

1. MySQL中的鎖 19篇

2. InnoDB存儲引擎 35篇

3. MySQL學(xué)習(xí)筆記 285篇

總結(jié)

行級鎖
  • 共享鎖(S鎖)
  • 排他鎖(X鎖)

\color{red}{1. 記錄鎖record lock}
即索引的記錄鎖,他建立在索引記錄上,很多時候,掃描一個表,如果沒有索引,往往會導(dǎo)致整個表被鎖住,建立合適的索引可以防止掃描整個表。

\color{red}{2. 間隙鎖gap lock}
這是施加于索引記錄間隙上的鎖

1、間隙鎖鎖定的是某個索引記錄之前和之后的一個間隙范圍。
2、間隙鎖之間互不影響,可以在鎖定的區(qū)間再次添加間隙鎖。
3、間隙鎖可能造成死鎖
4、間隙鎖是在RR隔離級別下特有的
5、間隙鎖只影響一般索引,對于唯一索引和主鍵,情況有些許不同,下篇文章我們會著重分析。

當(dāng)字段是唯一索引或者主鍵的時候,間隙鎖產(chǎn)生的規(guī)則如下:

  1. 如果查詢的結(jié)果中包含這個記錄,那么在另外的會話上插入該記錄前后間隙的記錄時,不會產(chǎn)生間隙鎖
  2. 如果查詢的結(jié)果中不包含這個記錄,那么在另外的會話上插入該記錄前后間隙的記錄時,會產(chǎn)生間隙鎖。

\color{red}{3. next-key(臨鍵)鎖}
記錄鎖 + 間隙鎖 的組合,他鎖定的是一個范圍,并且鎖定記錄本身。也就是說,next key鎖不是一個單獨的鎖,就我理解,它其實是一個概念,這個概念是由上面兩個鎖的概念組合而來的。有時候在開發(fā)的過程中,我們會發(fā)現(xiàn)在insert操作的時候,會鎖定相鄰的鍵,這就是一個next-key鎖技術(shù),\color{red}{MySQL用這個技術(shù)來避免“幻讀”。}

行鎖防止別的事務(wù)修改或刪除,GAP鎖防止別的事務(wù)新增,行鎖和GAP鎖的結(jié)合形成的Next-Key鎖共同解決了RR級別在寫數(shù)據(jù)時的幻讀問題。

幻讀

事務(wù)發(fā)現(xiàn)莫名地多了一條或多數(shù)據(jù),而且沒有被之前的update語句所修改。

行級鎖的優(yōu)點有:

1.在很多線程中訪問不同的行時只存在少量鎖定沖突;
2.回滾時只有少量的更改;
3.可以長時間鎖定單一的行;
需要注意的是,innodb中的鎖定技術(shù)往往是基于索引來實現(xiàn)的,如果我們的SQL語句中沒有利用到索引,那么innodb將會執(zhí)行一個全表掃描,鎖定所有的行。而鎖定過多的行往往又會導(dǎo)致問題,就是鎖之間的競爭激烈,降低了并發(fā)率,所以建立合適的索引是很重要的,innodb需要索引來過濾那些不需要訪問的行。

MySQL中獲得讀取鎖的SQL語法:

1共享鎖:  SELECT ... LOCK IN SHARE MODE 
2排它鎖:  SELECT ... FOR UPDATE

沒有索引的表,在進(jìn)行獲取排它鎖的時候,會鎖定整個表的所有記錄。查詢條件若有類型轉(zhuǎn)換,則不走索引,全表掃描。


當(dāng)我們對數(shù)據(jù)庫中的表進(jìn)行select、update、delete以及insert的時候,innodb存儲引擎會根據(jù)操作類型的不同來給這些操作添加具體的鎖。

MySQL中的兩種讀操作

\color{red}{快照讀:}
讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。簡單的select操作,屬于快照讀,不加鎖。(當(dāng)然,也有例外,下面會分析)

select * from table where id>10;

\color{red}{當(dāng)前讀:}
讀取的是記錄的最新版本,并且,當(dāng)前讀返回的記錄,都會加上鎖,保證其他事務(wù)不會再并發(fā)修改這條記錄。特殊的讀操作,插入/更新/刪除操作,屬于當(dāng)前讀,需要加鎖。

select * from table where id>10 lock in share mode; 
select * from table where id>10 for update;  
insert into table values (…);
update table set id=11 where id=10;
delete from table where id>10;

讀取之后,需要保證其他并發(fā)事務(wù)不能修改當(dāng)前記錄,對讀取記錄加鎖。其中,除了第一條語句明確指出了lock in share mode之外,也就是對讀取記錄加S鎖 (共享鎖)外,其他的操作,都加的是X鎖 (排它鎖)。

一致性非鎖定讀

?? 一致性非鎖定讀是指innodb通過行記錄的多版本控制來讀取當(dāng)前執(zhí)行時間數(shù)據(jù)庫中行的數(shù)據(jù),如果讀取的行正在執(zhí)行delete或者update操作,則會讀取一個該行記錄的一個快照數(shù)據(jù)。

select * from table where id>10;

一致性鎖定讀

讀取的就是當(dāng)前數(shù)據(jù)的真實內(nèi)容,它需要在讀取的時候給記錄進(jìn)行上鎖(必須在事務(wù)里面才管用,才能獲得鎖)

select * for update(X鎖定)
select * lock in share mode(S鎖定)

意向鎖(Intention Locks)

InnoDB支持多粒度鎖(multiple granularity locking),它允許行級鎖與表級鎖共存,實際應(yīng)用中,InnoDB使用的是意向鎖。意向鎖是指,未來的某個時刻,事務(wù)可能要加共享/排它鎖了,先提前聲明一個意向。
\color{red}{意向鎖特點}
(1)首先,意向鎖,是一個表級別的鎖(table-level locking);
(2)意向鎖分為:
意向共享鎖(intention shared lock, IS),它預(yù)示著,事務(wù)有意向?qū)Ρ碇械哪承┬屑庸蚕鞸鎖
意向排它鎖(intention exclusive lock, IX),它預(yù)示著,事務(wù)有意向?qū)Ρ碇械哪承┬屑优潘黊鎖
舉個例子:

select ... lock in share mode,要設(shè)置IS鎖;
select ... for update,要設(shè)置IX鎖;

(3)意向鎖協(xié)議(intention locking protocol)并不復(fù)雜:
事務(wù)要獲得某些行的S鎖,必須先獲得表的IS鎖
事務(wù)要獲得某些行的X鎖,必須先獲得表的IX鎖
(4)由于意向鎖僅僅表明意向,它其實是比較弱的鎖,意向鎖之間并不相互互斥,而是可以并行,其兼容互斥表如下:

        IS          IX
IS      兼容      兼容
IX      兼容      兼容

(5)額,既然意向鎖之間都相互兼容,那其意義在哪里呢?它會與共享鎖/排它鎖互斥,其兼容互斥表如下:

          S          X
IS      兼容      互斥
IX      互斥      互斥

畫外音:排它鎖是很強的鎖,不與其他類型的鎖兼容。這也很好理解,修改和刪除某一行的時候,必須獲得強鎖,禁止這一行上的其他并發(fā),以保障數(shù)據(jù)的一致性。

\color{red}{插入意向鎖}
插入意向鎖是一種間隙鎖,專門針對的是數(shù)據(jù)行的插入操作,多個事務(wù)插入相同的索引間隙時,只要不是插入到相同的位置,則不需要進(jìn)行鎖等待。

假設(shè)有索引記錄的值分別是4和7,單獨的事務(wù)分別嘗試插入5和6,在獲得插入行的排它鎖之前,每個事務(wù)都是用插入意圖鎖來鎖定4和7之間的空間,但是不會相互阻塞。因為行級別是沒有沖突的。

簡單理解就是插入意向鎖鎖定了索引之間的間隙,但是插入意向鎖之間沒有互相阻塞。

什么叫做覆蓋索引?

在了解覆蓋索引之前我們先大概了解一下什么是聚集索引(主鍵索引)和輔助索引(二級索引)

聚集索引(主鍵索引):

聚集索引就是按照每張表的主鍵構(gòu)造一顆B+樹,同時葉子節(jié)點中存放的即為整張表的記錄數(shù)據(jù)。
聚集索引的葉子節(jié)點稱為數(shù)據(jù)頁,聚集索引的這個特性決定了索引組織表中的數(shù)據(jù)也是索引的一部分。

輔助索引(二級索引):

非主鍵索引,葉子節(jié)點=鍵值+書簽。Innodb存儲引擎的書簽就是相應(yīng)行數(shù)據(jù)的主鍵索引值。
再來看看什么是覆蓋索引,有下面三種理解:

\color{red}{解釋一:} 就是select的數(shù)據(jù)列只用從索引中就能夠取得,不必從數(shù)據(jù)表中讀取,換句話說查詢列要被所使用的索引覆蓋。

\color{red}{解釋二:} 索引是高效找到行的一個方法,當(dāng)能通過檢索索引就可以讀取想要的數(shù)據(jù),那就不需要再到數(shù)據(jù)表中讀取行了。如果一個索引包含了(或覆蓋了)滿足查詢語句中字段與條件的數(shù)據(jù)就叫 做覆蓋索引。

\color{red}{解釋三:} 是非聚集組合索引的一種形式,它包括在查詢里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆蓋查詢語句[select子句]與查詢條件[Where子句]中所涉及的字段,也即,索引包含了查詢正在查找的所有數(shù)據(jù))。

不是所有類型的索引都可以成為覆蓋索引。覆蓋索引必須要存儲索引的列,而哈希索引、空間索引和全文索引等都不存儲索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引

當(dāng)發(fā)起一個被索引覆蓋的查詢(也叫作索引覆蓋查詢)時,在EXPLAIN的Extra列可以看到“Using index”的信息

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

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

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