溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

MySQL涉及加鎖的問題總結(jié)

發(fā)布時(shí)間:2020-03-30 16:34:50 來源:億速云 閱讀:106 作者:小新 欄目:MySQL數(shù)據(jù)庫

今天小編分享的是MySQL涉及加鎖的問題總結(jié),可能大家對(duì)MySQL并不陌生,或者從來沒有了解過MySQL。但是不用擔(dān)心,今天小編會(huì)以最簡單的描述來講解MySQL涉及加鎖的問題。一起來看看吧。

如何并發(fā)的訪問數(shù)據(jù)庫呢?答案就是加鎖。接下來說一下,數(shù)據(jù)庫的鎖機(jī)制,數(shù)據(jù)庫中都有哪些鎖?

  首先呢,鎖是一種并發(fā)控制技術(shù),鎖是用來在多個(gè)用戶同時(shí)訪問同一個(gè)數(shù)據(jù)的時(shí)候保護(hù)數(shù)據(jù)的。

MySQL涉及加鎖的問題總結(jié)

有2種基本的鎖類型:

  共享(S)鎖:多個(gè)事務(wù)可封鎖一個(gè)共享頁;任何事務(wù)都不能修改該頁;通常是該頁被讀取完畢,S鎖立即被釋放。在執(zhí)行select語句的時(shí)候需要給操作對(duì)象(表或一些記錄)加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒有,則可以加共享鎖(一個(gè)對(duì)象上可以加N個(gè)共享鎖),否則不行。共享鎖通常在執(zhí)行完select語句之后被釋放,當(dāng)然也可能是在事務(wù)結(jié)束(包括正常結(jié)束和異常結(jié)束)的時(shí)候被釋放,主要取決與數(shù)據(jù)庫所設(shè)置的事務(wù)隔離級(jí)別。

  排它(X)鎖:僅允許一個(gè)事務(wù)封鎖此頁;其他任何事務(wù)必須等到X鎖被釋放才能對(duì)該頁進(jìn)行訪問;X鎖一直到事務(wù)結(jié)束才能被釋放。執(zhí)行insert、update、delete語句的時(shí)候需要給操作的對(duì)象加排它鎖,在加排他鎖之前必須確認(rèn)該對(duì)象上沒有其他任何鎖,一旦加上排它鎖之后,就不能再給這個(gè)對(duì)象加其他任何鎖。排它鎖的釋放通常是在事務(wù)結(jié)束的時(shí)候(當(dāng)然也有例外,就是在數(shù)據(jù)庫事務(wù)隔離級(jí)別被設(shè)置為Read Uncommitted(讀未提交數(shù)據(jù))的時(shí)候,這種情況下排他鎖會(huì)在執(zhí)行完更新操作之后被釋放,而不是在事務(wù)結(jié)束的時(shí)候)。

按鎖的機(jī)制

既然使用了鎖,就有出現(xiàn)死鎖的可能。

產(chǎn)生死鎖的四個(gè)必要條件:

  互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。

  請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。

  不可剝奪條件:進(jìn)程已獲得的資源,在未使用完之前,不能強(qiáng)行剝奪。

  環(huán)路等待條件:若干個(gè)進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

只要系統(tǒng)發(fā)生了死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會(huì)發(fā)生死鎖。

MySQL涉及加鎖的問題總結(jié)

預(yù)防死鎖

預(yù)防死鎖的發(fā)生只需要破壞死鎖產(chǎn)生的四個(gè)必要條件之一即可。

1)破壞互斥條件

  如果允許系統(tǒng)資源都能共享使用,則系統(tǒng)不會(huì)進(jìn)入死鎖狀態(tài)。但有些資源根本不能同時(shí)訪問,如打印機(jī)等臨界資源只能互斥使用。所以破壞互斥條件而預(yù)防死鎖的方法不太可行,而且在有些場合應(yīng)該保護(hù)這種互斥性。

2)破壞不可剝奪條件

  當(dāng)一個(gè)已保持了某些不可剝奪資源的進(jìn)程,請(qǐng)求新的資源而得不到滿足時(shí),它必須釋放已經(jīng)保持的所有資源,待以后需要時(shí)再重新申請(qǐng)。這意味著,一個(gè)進(jìn)程已占有的資源會(huì)被暫時(shí)釋放,或者說是被剝奪了,或從而破壞了不可剝奪條件。

  該策略實(shí)現(xiàn)起來比較復(fù)雜,釋放已獲得的資源可能造成前一階段工作的失效,反復(fù)地申請(qǐng)和釋放資源會(huì)增加系統(tǒng)開銷,降低系統(tǒng)吞吐量。這種方法常用于狀態(tài)易于保存和恢復(fù)的資源,如CPU的寄存器及內(nèi)存資源,一般不能用于打印機(jī)之類的資源。

3)破壞請(qǐng)求和保持的條件

  采用預(yù)先靜態(tài)分配方法,即進(jìn)程在運(yùn)行前一次申請(qǐng)完它所需要的全部資源,在它的資源為滿足前,不把它投入運(yùn)行。一旦投入運(yùn)行后,這些資源就一直歸它所有,也不再提出其他資源請(qǐng)求,這樣就可以保證系統(tǒng)不會(huì)發(fā)生死鎖。

  這種方式實(shí)現(xiàn)簡單,但缺點(diǎn)也顯而易見,系統(tǒng)資源被嚴(yán)重浪費(fèi),其中有些資源可能僅在運(yùn)行初期或運(yùn)行快結(jié)束時(shí)才使用,甚至根本不使用。而且還會(huì)導(dǎo)致“饑餓”現(xiàn)象,當(dāng)由于個(gè)別資源長期被其他進(jìn)程占用時(shí),將致使等待該資源的進(jìn)程遲遲不能開始運(yùn)行。

MySQL涉及加鎖的問題總結(jié)

4)破壞環(huán)路等待條件

  為了破壞環(huán)路等待條件,可采用順序資源分配法。首先給系統(tǒng)中的資源編號(hào),規(guī)定每個(gè)進(jìn)程,必須按編號(hào)遞增的順序請(qǐng)求資源,同類資源一次申請(qǐng)完。也就是說,只要進(jìn)程提出申請(qǐng)分配資源Ri,則該進(jìn)程在以后的資源申請(qǐng)種,只能申請(qǐng)編號(hào)大于Ri的資源。

  這種方法存在的問題時(shí),編號(hào)必須相對(duì)穩(wěn)定,這就限制了新類型設(shè)備的增加;盡管在為資源編號(hào)時(shí)已考慮到大多數(shù)作業(yè)實(shí)際使用這些資源的順序,但也經(jīng)常會(huì)發(fā)生作業(yè)使用資源的順序與系統(tǒng)規(guī)定順序不同的情況,造成資源的浪費(fèi);此外,這種按規(guī)定次序申請(qǐng)資源的方法,也必然會(huì)給用戶的編程帶來麻煩。

解除死鎖

  1)從死鎖進(jìn)程處剝奪資源;

  2)終止部分或全部進(jìn)程;

MySQL鎖的粒度(即鎖的級(jí)別)

MySQL各存儲(chǔ)引擎使用了三種類型(級(jí)別)的鎖定機(jī)制:行級(jí)鎖定、頁級(jí)鎖定和表級(jí)鎖定。

  1、表級(jí)鎖:直接鎖定整張表,在你鎖定期間,其他進(jìn)程無法對(duì)該表進(jìn)行寫操作。如果你是寫鎖,則其他進(jìn)程則讀也不允許。特點(diǎn):開銷小,加鎖快;不會(huì)出現(xiàn)死鎖;鎖粒度最大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。

    MyISAM存儲(chǔ)引擎采用的是表級(jí)鎖。

    有兩種模式:表共享讀鎖和表獨(dú)占寫鎖。加讀鎖的命令:lock table 表名 read;  去掉鎖的命令:unlock tables。

    支持并發(fā)插入:支持查詢和插入操作并發(fā)運(yùn)行(在表尾并發(fā)插入)。

    鎖調(diào)度機(jī)制:寫鎖優(yōu)先。一個(gè)進(jìn)程請(qǐng)求某個(gè)MyISAM表的讀鎖,同時(shí)另一個(gè)進(jìn)程也請(qǐng)求同一表的寫鎖,MySQL如何處理呢?答案是寫進(jìn)程先獲得鎖。

  2、行級(jí)鎖:僅對(duì)指定的記錄進(jìn)行加鎖,這樣其他進(jìn)程還是可以對(duì)同一個(gè)表中的其他記錄進(jìn)行操作。特點(diǎn):開銷大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

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

  3、頁級(jí)鎖:一次鎖定相鄰的一組記錄。開銷和加鎖時(shí)間介于表鎖和行鎖之間;會(huì)出現(xiàn)死鎖;鎖定粒度介于表鎖和行鎖治安,并發(fā)度一般。

  最常用的處理多用戶并發(fā)訪問的方法是加鎖。當(dāng)一個(gè)用戶鎖定數(shù)據(jù)庫中的某個(gè)對(duì)象時(shí),其他用戶就不能再訪問該對(duì)象。加鎖對(duì)并發(fā)訪問的影響體現(xiàn)在鎖的粒度上。比如,(表鎖)放在一個(gè)表上的鎖限制對(duì)整個(gè)表的并發(fā)訪問;(頁鎖)放在數(shù)據(jù)頁上的鎖限制了對(duì)整個(gè)數(shù)據(jù)頁的訪問;(行鎖)放在行上的鎖只限制對(duì)該行的并發(fā)訪問。

樂觀鎖和悲觀鎖的概念,實(shí)現(xiàn)方式和使用場景

鎖有兩種機(jī)制:悲觀鎖和樂觀鎖。

  悲觀鎖,鎖如其名,它對(duì)世界是悲觀的,它認(rèn)為別人訪問正在改變的數(shù)據(jù)的概率是很高的,所以從數(shù)據(jù)開始更改時(shí)就將數(shù)據(jù)鎖住,直到更改完成才釋放。

MySQL涉及加鎖的問題總結(jié)

一個(gè)典型的依賴數(shù)據(jù)庫的悲觀鎖調(diào)用:

  select * from account where name="Erica" for update

  這條SQL語句鎖定了account表中所有符合檢索條件(name="Erica")的記錄。本事務(wù)提交之前(事務(wù)提交時(shí)會(huì)釋放事務(wù)過程中的鎖),外界無法修改這些記錄。該語句用來鎖定特定的行(如果where子句,就是滿足where條件的那些行)。當(dāng)這些行被鎖定后,其他會(huì)話可以選擇這些行,但不能更改或刪除這些行,直到該語句的事務(wù)被commit語句或rollback語句結(jié)束終止。需要注意的是,select ...for update要放到MySQL的事務(wù)種,即begin和commit中,否則不起作用。

  悲觀所可能會(huì)造成加鎖的時(shí)間很長,并發(fā)行不好,特別是長事務(wù),影響系統(tǒng)的整體性能。

  悲觀所的實(shí)現(xiàn)方式:

    悲觀鎖,也是基于數(shù)據(jù)庫的鎖機(jī)制實(shí)現(xiàn)。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖、寫鎖等,都是在做操作之前先上鎖。

  樂觀鎖,它對(duì)世界比較樂觀,認(rèn)為別人訪問正在改變的數(shù)據(jù)的概率是很低的,所以直到修改完成準(zhǔn)備提交所作的修改到數(shù)據(jù)庫的時(shí)候才會(huì)將數(shù)據(jù)鎖住,當(dāng)你讀取以及改變?cè)搶?duì)象時(shí)并不加鎖,完成更改后釋放。樂觀鎖不能解決臟讀的問題。

  樂觀鎖加鎖的時(shí)間要比悲觀鎖短,大大提升了大并發(fā)量下的系統(tǒng)整體性能表現(xiàn)。

  樂觀鎖的實(shí)現(xiàn)方式:

    1、大多是基于數(shù)據(jù)版本(version)記錄機(jī)制實(shí)現(xiàn),需要為每一行數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí)(也就是每一行數(shù)據(jù)多一個(gè)字段version),每次更新數(shù)據(jù)都要更新對(duì)應(yīng)的版本號(hào)+1。

    工作原理:讀出數(shù)據(jù)時(shí),將此版本一同讀出,之后更新時(shí),對(duì)此版本號(hào)加一。此時(shí),將提交的數(shù)據(jù)的版本信息與數(shù)據(jù)庫表對(duì)應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過期數(shù)據(jù),不得不重新讀取該對(duì)象并作出更改。

    2、使用時(shí)間戳來實(shí)現(xiàn)

    同樣是在需要樂觀鎖控制的table中增加一個(gè)字段,名稱無所謂,字段類型使用時(shí)間戳(timestamp),和上面的version類似,也是在更新提交的時(shí)候檢查當(dāng)前數(shù)據(jù)庫中數(shù)據(jù)的時(shí)間戳和自己更新前取到的時(shí)間戳進(jìn)行對(duì)比,如果一致則OK,否則就是版本沖突。

悲觀鎖與樂觀鎖的適用場景:

  如果并發(fā)量不大,可以使用悲觀鎖解決并發(fā)問題;但如果系統(tǒng)的并發(fā)量非常大的話,悲觀所定會(huì)帶來非常大的性能問題,所以我們就要選擇樂觀鎖定的方法?,F(xiàn)在大部分應(yīng)用都應(yīng)該是樂觀鎖的。

  以上就是MySQL涉及加鎖的問題總結(jié)的簡略介紹,當(dāng)然詳細(xì)使用上面的不同還得要大家自己使用過才領(lǐng)會(huì)。如果想了解更多,歡迎關(guān)注億速云行業(yè)資訊頻道哦!

  億速云的云數(shù)據(jù)庫MySQL,支持并提供“容災(zāi)、備份恢復(fù)、數(shù)據(jù)加密、數(shù)據(jù)遷移”等基本功能和解決方案,采用靈活的備份策略,配合多級(jí)備份體系,能夠?yàn)橛脩籼峁└踩€(wěn)定、可靠性更高的在線數(shù)據(jù)庫服務(wù)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI