MySQL表級鎖使用說明
表級鎖
該鎖會鎖定整張表,它是MySQL中最基本的鎖策略,并不依賴于存儲引擎(不管你是MySQL的什么存儲引擎,對于表鎖的策略都是一樣的),并且表鎖是開銷最小的策略(因為粒度比較大)。由于表級鎖一次會將整個表鎖定,所以可以很好的避免死鎖問題。當(dāng)然,鎖的粒度大所帶來最大的負(fù)面影響就是出現(xiàn)鎖資源爭用的概率也會最高,導(dǎo)致并發(fā)率大打折扣。
1、表級別的S鎖,X鎖
InnoDB存儲引擎
在對某個表執(zhí)行SELECT、INSERT、DELETE、UPDATE 語句時,InnoDB存儲引擎是不會為這個表添加表級別的S鎖或者X鎖的。
一般情況下,不會使用InnoDB存儲引擎提供的表級別的S鎖和X鎖。只會在一些特殊情況下,比方說崩潰恢復(fù)過程中用到。
InnoDB存儲引擎下,手動添加表t的S鎖或X鎖:
lock tables t read -- S鎖 lock tables t write -- X鎖
不過盡量避免在使用InnoDB存儲引擎的表上使用LOCK TABLES這樣的手動鎖表語句,它們并不會提供什么額外的保護(hù),只是會降低并發(fā)能力而已。
MyISAM存儲引擎
MyISAM 的表級鎖有2種模式,分別為:表共享讀鎖(S鎖) 和 表獨占寫鎖(X鎖)。
表共享讀鎖(S鎖):當(dāng)開啟事務(wù)A 獲取表共享讀鎖, 則其他新開啟事務(wù)只能讀取數(shù)據(jù),不能對操作的同張表進(jìn)行更新或者插入操作,刪除操作,
表獨占寫鎖(X鎖):當(dāng)開啟事務(wù)A 獲取獨占寫鎖,則其他新開啟的事物 讀取,新增,修改,刪除 等操作會處于阻塞狀態(tài), 只到 事務(wù)A 主動釋放鎖。
MyISAM存儲引擎下,手動添加表t的S鎖或X鎖:
lock tables t read -- S鎖 lock tables t write -- X鎖
可通過 show status like 'tables%'; 命令來 查看 mysql 內(nèi)部表級鎖定的情況:
2、意向鎖
意向鎖概述
InnoDB支持多粒度鎖(multiple granularity locking),它允許行級鎖與表級鎖共存,而意向鎖就是其中的一種表鎖。
==意向鎖的存在是為了協(xié)調(diào)行鎖和表鎖的關(guān)系,支持多粒度(表鎖與行鎖)的鎖并存。==
意向鎖是一種不與行級鎖沖突的表級鎖,這一點非常重要。
意向鎖分為兩種:
- 意向共享鎖(intention shared lock, IS):事務(wù)有意向?qū)Ρ碇械哪承┬屑庸蚕礞i(S鎖)
select column from table ... lock in share mode; --
- 意向排他鎖(intention exclusive lock, IX):事務(wù)有意向?qū)Ρ碇械哪承┬屑优潘i(X鎖)
select column from table ... for mode; --
申請意向鎖的動作是數(shù)據(jù)庫完成的,就是說,事務(wù)A申請一行的行鎖的時候,數(shù)據(jù)庫會自動先開始申請表的意向鎖,不需要我們程序員使用代碼來申請。
意向鎖解決的問題
事務(wù)A鎖住了表中的一行,讓這一行只能讀,不能寫。之后,事務(wù)B申請整個表的寫鎖。
如果事務(wù)B申請成功,那么理論上它就能修改表中的任意一行,這與A持有的行鎖是沖突的。
數(shù)據(jù)庫需要避免這種沖突,就是說要讓B的申請被阻塞,直到A釋放了行鎖。于是就有了意向鎖。
事務(wù)B只需檢查表上的意向鎖,發(fā)現(xiàn)表上有意向共享鎖IS,說明表中有些行被共享行鎖鎖住了,因此,事務(wù)B申請表的寫鎖會被阻塞。
在數(shù)據(jù)表的場景中,如果我們給某一行數(shù)據(jù)加上了排它鎖,數(shù)據(jù)庫會自動給更大一級的空間,比如數(shù)據(jù)頁或數(shù)據(jù)表加上意向鎖,告訴其他人這個數(shù)據(jù)頁或數(shù)據(jù)表已經(jīng)有人上過排它鎖了,這樣當(dāng)其他人想要獲取數(shù)據(jù)表排它鎖的時候,只需要了解是否有人已經(jīng)獲取了這個數(shù)據(jù)表的意向排他鎖即可。
- 如果事務(wù)想要獲得數(shù)據(jù)表中某些記錄的共享鎖,就需要在數(shù)據(jù)表上添加意向共享鎖。
- 如果事務(wù)想要獲得數(shù)據(jù)表中某些記錄的排他鎖,就需要在數(shù)據(jù)表上添加意向排他鎖。
意向鎖的并發(fā)性
開啟一個事務(wù),并給查詢記錄加上X鎖:此時針對查詢的記錄還加上了一個表級別的共享排它鎖(IX)
再開啟一個事務(wù),查詢不同記錄,并給查詢記錄加上X鎖:表級別的 IX共享排它鎖加鎖成功,因為兩次事務(wù)加的IX是針對不同的記錄的
結(jié)論:
- InnoDB支持多粒度鎖,特定場景下,行級鎖可以與表級鎖共存。
- 意向鎖之間互不排斥,但除了IS與S兼容外,意向鎖會與共享鎖/排他鎖互斥。
- lX,IS是表級鎖,不會和行級的X,S鎖發(fā)生沖突。只會和表級的X,S發(fā)生沖突。
- 意向鎖在保證并發(fā)性的前提下,實現(xiàn)了行鎖和表鎖共存且滿足事務(wù)隔離性的要求。
3、自增鎖(AUTO-INC鎖)
自增鎖是MySQL一種特殊的鎖,如果表中存在自增字段,當(dāng)向表中插入數(shù)據(jù)時,MySQL便會自動維護(hù)一個表級的自增鎖。
在執(zhí)行插入語句時就在表級別加一個AUTO-INC鎖,然后為每條待插入記錄的AUTO_INCREMENT修飾的列分配遞增的值,在該語句執(zhí)行結(jié)束后,再把AUTO-INC鎖釋放掉。
一個事務(wù)在持有AUTO-INC鎖的過程中,其他事務(wù)的插入語句都要被阻塞,可以保證一個語句中分配的遞增值是連續(xù)的。也正因為此,其并發(fā)性顯然并不高,當(dāng)我們向一個有AUTO_INCREMENT關(guān)鍵字的主鍵插入值的時候,每條語句都要對這個表鎖進(jìn)行競爭,這樣的并發(fā)潛力其實是很低下的。
所以 innodb 引擎通過設(shè)置 innodb_autoinc_lock_mode 的值來提供不同的鎖定機制,來顯著提高sQL語句的可伸縮性和性能。
innodb_autoinc_lock_mode有三個取值:0,1,2
tradition(innodb_autoinc_lock_mode = 0) 模式:==傳統(tǒng)==鎖定模式
- 它提供了一個向后兼容的能力
- 在這一模式下,所有類型的insert語句都會在語句開始的時候得到一個表級的auto_inc鎖,用于插入具有auto_inc列的表,在語句結(jié)束的時候才釋放這把鎖,注意,這里說的是語句級而不是事務(wù)級的,一個事務(wù)可能包涵有一個或多個語句。
- 它能保證值分配的可預(yù)見性,與連續(xù)性,可重復(fù)性,這個也就保證了insert語句在復(fù)制到slave的時候還能生成和master那邊一樣的值(它保證了基于語句復(fù)制的安全)。
- 由于在這種模式下auto_inc鎖一直要保持到語句的結(jié)束,所以這個就影響到了并發(fā)的插入。因為是表級鎖,當(dāng)在同一時間多個事務(wù)中執(zhí)行 insert 的時候,對于auto_inc鎖的爭奪會限制并發(fā)能力。
consecutive(innodb_autoinc_lock_mode = 1) 模式:==連續(xù)==鎖定模式
- 在MySQL8.0之前,==連續(xù)==鎖定模式是默認(rèn)的添加模式
- 這一模式在simple insert (要插入的行數(shù)已知)做了優(yōu)化,由于simple insert一次性插入值的個數(shù)可以立馬得到確定,所以mysql可以一次生成幾個連續(xù)的值,用于這個insert語句;總的來說這個對復(fù)制也是安全的 (它保證了基于語句復(fù)制的安全)
- 這一模式也是mysql的默認(rèn)模式,這個模式的好處是auto_inc鎖不要一直保持到語句的結(jié)束,只要語句得到了相應(yīng)的值后就可以提前釋放鎖
interleaved(innodb_autoinc_lock_mode = 2) 模式:==交錯==鎖定模式
- 在MySQL8.0,==交錯==鎖定模式是默認(rèn)的添加模式
- 由于這個模式下所有insert語句都不回使用表級auto_inc鎖,并且可以同時執(zhí)行多個語句,這是最快和最可擴展的鎖定模式,所以這個模式下的性能是最好的;但是它也有一個問題,由于多個語句可以同時生成數(shù)字,為任何給定語句插入的行生成的值可能是不連續(xù)的。
4、元數(shù)據(jù)鎖(MDL鎖)
在對某個表執(zhí)行一些諸如ALTER TABLE、DROP TABLE 這類的 DDL 語句時,其他事務(wù)對這個表并發(fā)執(zhí)行諸如 SELECT、INSERT、DELETE、UPDATE的語句會發(fā)生阻塞。
同理,某個事務(wù)中對某個表執(zhí)行SELECT、INSERT、DELETE、UPDATE語句時,在其他會話中對這個表執(zhí)行DDL語句也會發(fā)生阻塞。
這個過程其實是通過在server層使用一種稱之為元數(shù)據(jù)鎖(英文名: Metadata Locks,簡稱MDL)結(jié)構(gòu)來實現(xiàn)的。
MySQL5.5引入了meta data lock,簡稱MDL鎖,屬于表鎖范疇。MDL的作用是,保證讀寫的正確性。比如,如果一個查詢正在遍歷一個表中的數(shù)據(jù),而執(zhí)行期間另一個線程對這個表結(jié)構(gòu)做變更,增加了一列,那么查詢線程拿到的結(jié)果跟表結(jié)構(gòu)對不上,肯定是不行的。
因此,當(dāng)對一個表做增刪改查操作的時候,加MDL讀鎖;當(dāng)要對表做結(jié)構(gòu)變更操作的時候,加MDL寫鎖。
==讀鎖之間不互斥,因此你可以有多個線程同時對一張表增刪改查。讀鎖和寫鎖之間、寫鎖和寫鎖之間是互斥的==,用來保證變更表結(jié)構(gòu)操作的安全性,解決了 DML 和 DDL 操作之間的一致性問題。MDL鎖不需要顯式使用,在訪問一個表的時候會被自動加上。
以上就是MySQL表級鎖使用說明的詳細(xì)內(nèi)容,更多關(guān)于MySQL 表級鎖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySQL系列之redo log、undo log和binlog詳解
這篇文章主要介紹了MySQL系列之redo log、undo log和binlog詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12MySQL數(shù)據(jù)庫之?dāng)?shù)據(jù)表操作DDL數(shù)據(jù)定義語言
這篇文章主要介紹了MySQL數(shù)據(jù)庫之?dāng)?shù)據(jù)表操作DDL數(shù)據(jù)定義語言,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08詳解MySQL數(shù)據(jù)庫優(yōu)化的八種方式(經(jīng)典必看)
關(guān)于數(shù)據(jù)庫優(yōu)化,網(wǎng)上有不少資料和方法,但是不少質(zhì)量參差不齊,有些總結(jié)的不夠到位,內(nèi)容冗雜。今天給大家分享一篇文章關(guān)于mysql數(shù)據(jù)庫優(yōu)化的八種方式,非常經(jīng)典,需要的的朋友參考下2017-03-03