溫馨提示×

溫馨提示×

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

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

Mysql鎖是什么東西

發(fā)布時(shí)間:2021-08-18 09:39:54 來源:億速云 閱讀:145 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“Mysql鎖是什么東西”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Mysql鎖是什么東西”吧!

數(shù)據(jù)庫鎖設(shè)計(jì)的初衷是處理并發(fā)問題。作為多用戶共享的資源,當(dāng)出現(xiàn)并發(fā)訪問的時(shí)候,數(shù)據(jù)庫需要合理地控制資源的訪問規(guī)則。而鎖就是用來 實(shí)現(xiàn)這些訪問規(guī)則的重要數(shù)據(jù)結(jié)構(gòu)

根據(jù)加鎖的范圍,MySQL 里面的鎖大致可以分成全局鎖、表級鎖和行鎖三類

全局鎖

全局鎖就是對整個(gè)數(shù)據(jù)庫實(shí)例加鎖。MySQL 提供了一個(gè)加全局讀鎖的方法, 命令是 Flush tables with read lock (FTWRL)。當(dāng)你需要讓整個(gè)庫處于只讀狀態(tài)的時(shí)候,可以使用這個(gè)命令,之后其他線程的以下語句會(huì)被阻塞:數(shù)據(jù)更新語句(數(shù)據(jù)的增刪改)、數(shù)據(jù)定義語句(包括建表、修改表結(jié)構(gòu)等)和更新類事務(wù)的提交語句

全局鎖的典型使用場景是,做全庫邏輯備份

但是讓整庫都只讀,聽上去就很危險(xiǎn):

如果你在主庫上備份,那么在備份期間都不能執(zhí)行更新,業(yè)務(wù)基本上就得停擺; 如果你在從庫上備份,那么備份期間從庫不能執(zhí)行主庫同步過來的 binlog,會(huì)導(dǎo)致主從 延遲

官方自帶的邏輯備份工具是 mysqldump。當(dāng) mysqldump 使用參數(shù)–single-transaction 的時(shí)候,導(dǎo)數(shù)據(jù)之前就會(huì)啟動(dòng)一個(gè)事務(wù),來確保拿到一致性視圖。而由于 MVCC 的支持, 這個(gè)過程中數(shù)據(jù)是可以正常更新的

有了這個(gè)功能,為什么還需要 FTWRL 呢?一致性讀是好,但前提是引擎 要支持這個(gè)隔離級別。比如,對于 MyISAM 這種不支持事務(wù)的引擎,如果備份過程中有更新,總是只能取到最新的數(shù)據(jù),那么就破壞了備份的一致性。這時(shí),我們就需要使用 FTWRL 命令了

表級鎖

MySQL 里面表級別的鎖有兩種:一種是表鎖,一種是元數(shù)據(jù)鎖

表鎖的語法是 lock tables ... read/write。與 FTWRL 類似,可以用 unlock tables 主動(dòng) 釋放鎖,也可以在客戶端斷開的時(shí)候自動(dòng)釋放。需要注意,lock tables 語法除了會(huì)限制別 的線程的讀寫外,也限定了本線程接下來的操作對象

另一類表級的鎖是 MDL(metadata lock)。MDL 不需要顯式使用,在訪問一個(gè)表的時(shí) 候會(huì)被自動(dòng)加上。MDL 的作用是,保證讀寫的正確性。你可以想象一下,如果一個(gè)查詢正 在遍歷一個(gè)表中的數(shù)據(jù),而執(zhí)行期間另一個(gè)線程對這個(gè)表結(jié)構(gòu)做變更,刪了一列,那么查 詢線程拿到的結(jié)果跟表結(jié)構(gòu)對不上,肯定是不行的

因此,在 MySQL 5.5 版本中引入了 MDL,當(dāng)對一個(gè)表做增刪改查操作的時(shí)候,加 MDL 讀鎖;當(dāng)要對表做結(jié)構(gòu)變更操作的時(shí)候,加 MDL 寫鎖

讀鎖之間不互斥,因此你可以有多個(gè)線程同時(shí)對一張表增刪改查。讀寫鎖之間、寫鎖之間是互斥的,用來保證變更表結(jié)構(gòu)操作的安全性。因此,如果有兩個(gè)線程要同時(shí)給一個(gè)表加字段,其中一個(gè)要等另一個(gè)執(zhí)行完才能開始執(zhí)行

事務(wù)中的 MDL 鎖,在語句執(zhí)行開始時(shí)申請,但是語句結(jié)束后并不會(huì) 馬上釋放,而會(huì)等到整個(gè)事務(wù)提交后再釋放

如何安全地給表加字段?

  • 首先我們要解決長事務(wù),事務(wù)不提交,就會(huì)一直占著 MDL 鎖

  • 比較理想的機(jī)制是,在 alter table 語句里面設(shè)定等待時(shí)間,如果在這個(gè)指定的等待時(shí)間里面能夠拿到 MDL 寫鎖最好,拿不 到也不要阻塞后面的業(yè)務(wù)語句,先放棄

行鎖

MySQL 的行鎖是在引擎層由各個(gè)引擎自己實(shí)現(xiàn)的。但并不是所有的引擎都支持行鎖,比 如 MyISAM 引擎就不支持行鎖。不支持行鎖意味著并發(fā)控制只能使用表鎖,對于這種引擎的表,同一張表上任何時(shí)刻只能有一個(gè)更新在執(zhí)行,這就會(huì)影響到業(yè)務(wù)并發(fā)度。InnoDB 是支持行鎖的,這也是 MyISAM 被 InnoDB 替代的重要原因之一

兩階段鎖

在 InnoDB 事務(wù)中,行鎖是在需要的時(shí)候才加上的,但并不是不需要了就立刻 釋放,而是要等到事務(wù)結(jié)束時(shí)才釋放。這個(gè)就是兩階段鎖協(xié)議

如果你的事務(wù)中需要鎖多個(gè)行,要把最可能造成鎖沖突、最可能影響并發(fā)度的鎖盡量往后放

死鎖和死鎖檢測

當(dāng)并發(fā)系統(tǒng)中不同線程出現(xiàn)循環(huán)資源依賴,涉及的線程都在等待別的線程釋放資源時(shí),就會(huì)導(dǎo)致這幾個(gè)線程都進(jìn)入無限等待的狀態(tài),稱為死鎖

當(dāng)出現(xiàn)死鎖以后,有兩種策略:

一種策略是,直接進(jìn)入等待,直到超時(shí)。這個(gè)超時(shí)時(shí)間可以通過參數(shù) innodb_lock_wait_timeout 來設(shè)置。另一種策略是,發(fā)起死鎖檢測,發(fā)現(xiàn)死鎖后,主動(dòng)回滾死鎖鏈條中的某一個(gè)事務(wù),讓其 他事務(wù)得以繼續(xù)執(zhí)行。將參數(shù) innodb_deadlock_detect 設(shè)置為 on,表示開啟這個(gè)邏輯

正常情況下我們還是要采用第二種策略,即:主動(dòng)死鎖檢測,而且 innodb_deadlock_detect 的默認(rèn)值本身就是 on。主動(dòng)死鎖檢測在發(fā)生死鎖的時(shí)候,是 能夠快速發(fā)現(xiàn)并進(jìn)行處理的,但是它也是有額外負(fù)擔(dān)的

每當(dāng)一個(gè)事務(wù)被鎖的時(shí)候,就要看看它所依賴的線程有沒有被別人鎖住,如此循環(huán),最后判斷是否出現(xiàn)了循環(huán)等待,也就是死鎖

那如果是我們上面說到的所有事務(wù)都要更新同一行的場景呢?

每個(gè)新來的被堵住的線程,都要判斷會(huì)不會(huì)由于自己的加入導(dǎo)致了死鎖,這是一個(gè)時(shí)間復(fù)雜度是 O(n) 的操作。假設(shè)有 1000 個(gè)并發(fā)線程要同時(shí)更新同一行,那么死鎖檢測操作就是100萬這個(gè)量級的。雖然最終檢測的結(jié)果是沒有死鎖,但是這期間要消耗大量的 CPU 資源

怎么解決由這種熱點(diǎn)行更新導(dǎo)致的性能問題呢?

一個(gè)思路是控制并發(fā)度。根據(jù)上面的分析,你會(huì)發(fā)現(xiàn)如果并發(fā)能夠控制住,比如同一行 同時(shí)最多只有 10 個(gè)線程在更新,那么死鎖檢測的成本很低,就不會(huì)出現(xiàn)這個(gè)問題

這個(gè)并發(fā)控制要做在數(shù)據(jù)庫服務(wù)端。如果你有中間件,可以考慮在中間件實(shí)現(xiàn);如 果你的團(tuán)隊(duì)有能修改 MySQL 源碼的人,也可以做在 MySQL 里面?;舅悸肪褪?,對于 相同行的更新,在進(jìn)入引擎之前排隊(duì)

還可以考慮通過將一行改成邏輯上的多行來減少鎖沖突

感謝各位的閱讀,以上就是“Mysql鎖是什么東西”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Mysql鎖是什么東西這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

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

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

AI