mysql鎖的學(xué)習(xí)心得

作為一個(gè)程序員我相信鎖的概念對(duì)你來說一定不會(huì)很陌生,在開發(fā)的過程中都或多或少的接觸過,我們都知道鎖的種類一般分為樂觀鎖和悲觀鎖兩種,不管是悲觀鎖還是樂觀鎖都是為了解決并發(fā)問題的.

樂觀鎖

樂觀鎖的實(shí)現(xiàn)用的是一種沖突檢驗(yàn)的思想,當(dāng)線程對(duì)一條數(shù)據(jù)進(jìn)行寫操作時(shí),先判斷他是否被修改過,如果沒有那么可以執(zhí)行寫操作,否則丟棄該操作或重試操作,在整個(gè)的執(zhí)行過程中其實(shí)都沒有對(duì)數(shù)據(jù)進(jìn)行加鎖;

悲觀鎖

悲觀鎖的實(shí)現(xiàn)是在沖突未產(chǎn)生之前事先對(duì)資源進(jìn)行加鎖,確保同一時(shí)刻只有有限的線程能夠訪問該資源,其他想要嘗試獲取資源的操作都會(huì)進(jìn)入等待狀態(tài),直到該線程完成了對(duì)資源的操作并且釋放了鎖后,其他線程才能重新操作資源;

樂觀鎖和悲觀鎖的使用

當(dāng)我們使用樂觀鎖的時(shí)候不用考慮死鎖的問題,但是由于樂觀鎖的實(shí)現(xiàn)基于沖突檢驗(yàn),所以當(dāng)沖突頻率重試成本較高時(shí)更推薦使用悲觀鎖,而需要非常高的響應(yīng)速度并且并發(fā)量非常大的時(shí)候使用樂觀鎖就能較好的解決問題,在這時(shí)使用悲觀鎖就可能出現(xiàn)嚴(yán)重的性能問題;在選擇并發(fā)控制機(jī)制時(shí),需要綜合考慮上面的四個(gè)方面(沖突頻率、重試成本、響應(yīng)速度和并發(fā)量)進(jìn)行選擇。

鎖的種類

我們都知道對(duì)于數(shù)據(jù)的操作無非是兩種,所以innodb在實(shí)現(xiàn)鎖的時(shí)候?qū)@兩種操作使用不同的鎖,他們分別是共享鎖(Shared Lock)和互斥鎖(Exclusive Lock);

共享鎖(讀鎖):允許事務(wù)對(duì)一條行數(shù)據(jù)進(jìn)行讀??;

互斥鎖(寫鎖):允許事務(wù)對(duì)一條行數(shù)據(jù)進(jìn)行刪除或更新;

讀默認(rèn)共享,寫默認(rèn)排他.

鎖的粒度

innodb支持表鎖和行鎖兩種不同粒度的鎖.

行鎖

innodb實(shí)現(xiàn)了標(biāo)準(zhǔn)的行鎖,也就是行共享鎖(Shared Lock)和行互斥鎖(Exclusive Lock)

行共享鎖:當(dāng)innodb搜索表索引時(shí),它會(huì)在遇到的索引記錄上設(shè)置共享鎖.

行排他鎖:當(dāng)innodb掃描表索引時(shí),它會(huì)在遇到的索引記錄上設(shè)置排他鎖.

無論是共享鎖還是互斥鎖其實(shí)都只是對(duì)某一個(gè)數(shù)據(jù)行進(jìn)行加鎖;為了支持多粒度鎖定,InnoDB 存儲(chǔ)引擎引入了意向鎖(Intention Lock),意向鎖就是一種表級(jí)鎖。

表鎖

與行鎖的種類相似的是,意向鎖也分為兩種:

意向共享鎖:事務(wù)想要在獲得表中某些記錄的共享鎖,需要在表上先加意向共享鎖;

意向互斥鎖:事務(wù)想要在獲得表中某些記錄的互斥鎖,需要在表上先加意向互斥鎖;

隨著意向鎖的加入,鎖類型之間的兼容矩陣也變得愈加復(fù)雜:


意向鎖的意義

意向鎖其實(shí)不會(huì)阻塞全表掃描之外的任何請(qǐng)求,它們的主要目的是為了標(biāo)識(shí)表中的某一行數(shù)據(jù)是否已經(jīng)被請(qǐng)求鎖定了

看到這里可能你會(huì)有一些疑惑?為什么意向鎖是這樣設(shè)計(jì)的?

你可以設(shè)想一下這樣的情景

如果沒有意向鎖,當(dāng)已經(jīng)有人使用行鎖對(duì)表中的某一行進(jìn)行修改時(shí),如果另外一個(gè)請(qǐng)求要對(duì)全表進(jìn)行修改,那么就需要對(duì)所有的行是否被鎖定進(jìn)行掃描,在這種情況下,效率是非常低的;不過,在引入意向鎖之后,當(dāng)有人使用行鎖對(duì)表中的某一行進(jìn)行修改之前,會(huì)先為表添加意向互斥鎖(IX),再為行記錄添加互斥鎖(X),在這時(shí)如果有人嘗試對(duì)全表進(jìn)行修改就不需要判斷表中的每一行數(shù)據(jù)是否被加鎖了,只需要通過等待意向互斥鎖被釋放就可以了。

鎖的實(shí)現(xiàn)

前面簡(jiǎn)單的介紹了一些鎖的概念,了解了在對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫時(shí)會(huì)獲取不同的鎖,接下來我將介紹innodb是如何將鎖添加到對(duì)應(yīng)的數(shù)據(jù)行上的,我們會(huì)分別介紹幾種鎖的算法:Record Lock、Gap Lock 和 Next-Key Lock等。官方文檔

Record Lock(記錄鎖)

記錄鎖是對(duì)索引記錄的鎖定,剛剛介紹過innodb在搜索或掃描表索引時(shí),它會(huì)在遇到的索引記錄上設(shè)置共享鎖或排他鎖。因此,記錄鎖可以理解為行鎖的實(shí)現(xiàn).

記錄鎖例子描述

CREATE TABLE users (id INT NOT NULL AUTO_INCREMENT, last_name VARCHAR(255) NOT NULL, first_name VARCHAR(255), age INT , PRIMARYKEY(id) , KEY(last_name) , KEY(age))engine=innodb;

當(dāng)我們使用 索引鍵(id?或者?last_name )作為 SQL 中?WHERE?語句的過濾條件時(shí),InnoDB 會(huì)通過索引建立的 B+ 樹找到行記錄并添加記錄鎖,但是如果使用?first_name?作為過濾條件時(shí),由于 InnoDB 不知道待操作的記錄具體存放的位置,也無法對(duì)將要操作哪條記錄提前做出判斷就會(huì)鎖定整個(gè)表。

Gap Lock(間隙鎖)

間隙鎖是對(duì)索引記錄中的一段連續(xù)區(qū)域的鎖定;InnoDB實(shí)現(xiàn)間隙鎖是用來防止其他事務(wù)對(duì)間隙進(jìn)行操作的。間隙鎖是可以共存的。意思是當(dāng)一個(gè)事務(wù)占用的間隙鎖時(shí)不會(huì)阻止另一個(gè)事務(wù)在同一個(gè)間隙上進(jìn)行間隙鎖定。共享和排他間隙鎖之間沒有區(qū)別。它們彼此不沖突,它們執(zhí)行相同的功能。

間隙鎖例子描述

當(dāng)使用類似?SELECT * FROM users WHERE id BETWEEN 10 AND 20 FOR UPDATE;的 SQL 語句時(shí),innodb就會(huì)在[10,20]之間加上間隙鎖用來阻止其他事務(wù)對(duì) 10<=id<=20 記錄的操作,間隙可以跨越單個(gè)索引值,多個(gè)索引值,甚至可能為空。

Next-Key Lock

Next-Key 鎖相比前兩者就稍微有一些復(fù)雜,是索引記錄上的記錄鎖和索引記錄之前的間隙上的間隙鎖的組合。

Next-Key Lock例子描述

假設(shè)索引包含值10,11,13和20.此索引的可能的下一個(gè)鍵鎖定包括以下間隔,其中圓括號(hào)表示排除間隔端點(diǎn),方括號(hào)表示包含端點(diǎn):

(negative infinity, 10]

(10, 11]

(11, 13]

(13, 20]

(20, positive infinity)

默認(rèn)情況下,InnoDB以?REPEATABLE READ事務(wù)隔離級(jí)別運(yùn)行。在這種情況下,InnoDB使用下一鍵鎖進(jìn)行搜索和索引掃描,這會(huì)阻止幻影行(請(qǐng)參見第14.7.4節(jié)“幻影行”)。

插入意向鎖

插入意向鎖是一種專門針對(duì)insert操作的鎖,假設(shè)在插入前,該間隙已經(jīng)有間隙鎖,那么Insert會(huì)申請(qǐng)插入意向鎖。插入意向鎖是這樣設(shè)計(jì)的:如果插入到相同索引間隙中的多個(gè)事務(wù)不插入間隙內(nèi)的相同位置,則不需要等待彼此。假設(shè)存在值為4和7的索引記錄。兩個(gè)事物分別嘗試插入值5和6,在獲取插入行上的排它鎖之前,每個(gè)事物都可以對(duì)4和7之間的間隙加插入意向鎖,并且不要互相阻塞因?yàn)樾惺欠菦_突的。

插入意向鎖例子描述

客戶端A創(chuàng)建一個(gè)包含兩個(gè)索引記錄(90和102)的表,然后啟動(dòng)一個(gè)事務(wù),該事務(wù)對(duì)ID大于100的索引記錄放置排他鎖。排他鎖包括記錄102之前的間隙鎖:

mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;

mysql> INSERT INTO child (id) values (90),(102);mysql> START TRANSACTION;

mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;

|+-----+|

? ? id

|+-----+|

? ? 102

|+-----+|

客戶端B開始事務(wù)以將記錄插入間隙。該事務(wù)在等待獲取獨(dú)占鎖時(shí)采用插入意向鎖。

mysql>STARTTRANSACTION;

mysql>INSERTINTOchild(id)VALUES(101);


AUTO-INC Locks

AUTO-INC鎖是當(dāng)向使用含有AUTO_INCREMENT列的表中插入數(shù)據(jù)時(shí)需要獲取的一種特殊的表級(jí)鎖

在最簡(jiǎn)單的情況下,如果一個(gè)事務(wù)正在向表中插入值,則任何其他事務(wù)必須等待對(duì)該表執(zhí)行自己的插入操作,以便第一個(gè)事務(wù)插入的行的值是連續(xù)的。

innodb_autoinc_lock_mode配置選項(xiàng)控制用于自動(dòng)增量鎖定的算法。 它允許您選擇如何在可預(yù)測(cè)的自動(dòng)遞增值序列和插入操作的最大并發(fā)性之間進(jìn)行權(quán)衡。

有關(guān)更多信息,請(qǐng)參見?第14.6.1.4節(jié)“InnoDB中的AUTO_INCREMENT處理”。

謂詞鎖

InnoDB支持SPATIAL?對(duì)包含空間列的列進(jìn)行索引(請(qǐng)參見?第11.5.8節(jié)“優(yōu)化空間分析”)。

要處理涉及SPATIAL索引的操作的鎖定?,Next-Key Lock不能很好地支持REPEATABLE READ或?SERIALIZABLE事務(wù)隔離級(jí)別。多維數(shù)據(jù)中沒有絕對(duì)排序概念,因此不清楚哪個(gè)是?“?下一個(gè)”密鑰。

要為具有SPATIAL索引的表啟用隔離級(jí)別?,請(qǐng)InnoDB?使用謂詞鎖。



聲明:文章圖片以及相關(guān)資料來自https://draveness.me/mysql-innodb.html

如有侵犯您的知識(shí)產(chǎn)權(quán)和版權(quán)問題,請(qǐng)通知本人,本人會(huì)即時(shí)做出處理刪除文章。

如果本博客的文章在知識(shí)點(diǎn)上有錯(cuò)誤,歡迎指出錯(cuò)誤所在,歡迎多多交流。謝謝!

參考資料:https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=https%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2F5.7%2Fen%2Finnodb-locking.html&skey=%40crypt_f43a8450_c582350c5419370ab04199879640e46e&deviceid=e041497283477858&pass_ticket=undefined&opcode=2&scene=1&username=@4aec4a8ea53f992132048ffa91dbdf31aa74fc618da5fb4fd03902c20da5a7b4

?著作權(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ù)。

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

  • 一、概述 數(shù)據(jù)庫(kù)鎖定機(jī)制簡(jiǎn)單來說,就是數(shù)據(jù)庫(kù)為了保證數(shù)據(jù)的一致性,而使各種共享資源在被并發(fā)訪問變得有序所設(shè)計(jì)的一種...
    忘憂谷主閱讀 638評(píng)論 0 3
  • 文章導(dǎo)讀: 累兮,累兮,要死兮...... 本文解決問題: 1、表級(jí)鎖定(讀鎖、寫鎖) 2、行級(jí)鎖定(共享鎖、排他...
    創(chuàng)造new_world閱讀 704評(píng)論 0 1
  • 一、概述 數(shù)據(jù)庫(kù)鎖定機(jī)制簡(jiǎn)單來說,就是數(shù)據(jù)庫(kù)為了保證數(shù)據(jù)的一致性,而使各種共享資源在被并發(fā)訪問變得有序所設(shè)計(jì)的一種...
    不變甄心閱讀 2,804評(píng)論 0 3
  • 想象,這種特質(zhì),沒有它,既成不了詩(shī)人、作家、藝術(shù)家、哲學(xué)家,也成為不了有機(jī)智的人、理性的生物、有思維的高級(jí)生命,也...
    趙禍禍閱讀 188評(píng)論 1 2
  • 我是一只修行千年的狐 千年修行 千年孤獨(dú) 那日在橋上第一次看見了你 就被你的儒雅的氣質(zhì)深深吸引 奈何我卻是一只狐 ...
    幻云流年閱讀 302評(píng)論 14 13

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