seo網(wǎng)站做推廣的公司輔導(dǎo)班培訓(xùn)機(jī)構(gòu)
1.什么是鎖
鎖是計(jì)算機(jī)協(xié)調(diào)多個(gè)進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制。
在數(shù)據(jù)庫中,數(shù)據(jù)是供許多用戶共享的資源,數(shù)據(jù)庫必須保證數(shù)據(jù)并發(fā)訪問的一致性、有效性,這就要靠鎖來協(xié)調(diào)實(shí)現(xiàn)。
MySOL中的鎖,分為以下三類:
(1)全局鎖:鎖定數(shù)據(jù)庫中的所有表
(2)表級鎖:每次操作鎖住整張表
(3)行級鎖:每次操作鎖住對應(yīng)的行數(shù)據(jù)
2.全局鎖
2.1全局鎖的作用
全局鎖就是對整個(gè)數(shù)據(jù)庫實(shí)例加鎖,加鎖后整個(gè)實(shí)例就處于只讀狀態(tài)(DML、DDL不可執(zhí)行,DQL可執(zhí)行)已經(jīng)更新操作的事務(wù)提交語句都將被阻塞。
其典型的使用場景是做全庫的邏輯備份,對所有的表進(jìn)行鎖定,保證數(shù)據(jù)的完整性、一致性。
數(shù)據(jù)庫的備份是逐表進(jìn)行的,可能剛剛完成了A表的備份,與A表相關(guān)的B表又更新了數(shù)據(jù),造成了數(shù)據(jù)的不一致,因此備份前要加上全局鎖
2.2實(shí)例備份
2.2.1使用全局鎖的方法
(1)先進(jìn)入數(shù)據(jù)庫,通過以下命令創(chuàng)建全局鎖:
flush tables with read lock;
(2)創(chuàng)建全局鎖后,退出數(shù)據(jù)庫,在windows或linux的命令行界面使用以下命令進(jìn)行備份:
mysqldump -u登錄數(shù)據(jù)庫的用戶?-p密碼 數(shù)據(jù)庫名>文件名
#-u與-p和后面的內(nèi)容之間是沒有空格的
#命令中的文件名,指的就是數(shù)據(jù)被復(fù)制后,存儲到了這個(gè)文件里
#如果操作的不是本地?cái)?shù)據(jù)庫,而是遠(yuǎn)程連接的,那么就需要在命令里加上 -h 遠(yuǎn)程數(shù)據(jù)庫ip
(3)備份完成后,再進(jìn)入數(shù)據(jù)庫,輸入以下命令解開全局鎖:
unlock tables;
2.2.2不使用全局鎖的方法
由于數(shù)據(jù)庫中加全局鎖是一個(gè)比較重的操作,且存在以下問題:
(1)如果在主庫上備份,那么在備份期間都不能執(zhí)行更新,業(yè)務(wù)基本上就得停擺。
(2)如果在從庫上備份,那么在備份期間從庫不能執(zhí)行主庫同步過來的二進(jìn)制日志(binlog),會導(dǎo)致主從延遲
因此實(shí)際生產(chǎn)中要慎用全局鎖。
在InnoDB引擎環(huán)境下,還有一種不使用全局鎖實(shí)現(xiàn)一致性備份數(shù)據(jù)庫的方法,只需在mysqldump命令里添加一個(gè)參數(shù)即可:
mysqldump --single-transaction -u登錄數(shù)據(jù)庫的用戶?-p密碼 數(shù)據(jù)庫名>文件名
#注意--single-transaction沒有空格
3.表級鎖
表級鎖,每次操作鎖住整張表。鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。應(yīng)用在MyISAM、InnoDB、BDB等存儲引擎中。
對于表級鎖,主要分為以下三類:
(1)表鎖
(2)元數(shù)據(jù)鎖(meta data lock,MDL)
(3)意向鎖
3.1表鎖
表鎖分為兩類:
(1)表共享讀鎖,簡稱讀鎖
(2)表獨(dú)占寫鎖,簡稱寫鎖
執(zhí)行鎖操作的會話 | 其他會話 | |
讀鎖 | 只可讀(只能DQL,不能DML、DDL) | 只可讀(只能DQL,不能DML、DDL) |
寫鎖 | 可讀可寫(DQL、DML、DDL都可以) | 不可讀不可寫(DQL、DML、DDL都不可以) |
語法:
lock tables 表名 read或write;
#加鎖
unlock tables;
#解鎖,這條命令會解鎖當(dāng)前會話下的所有表鎖
表鎖是以會話為分界的,而不是以客戶端為分界的,也不是以mysql用戶為分界的。也就是說,在當(dāng)前會話加了寫鎖,其他會話就無法讀寫(哪怕是同一客戶端同一mysql用戶)
3.2元數(shù)據(jù)鎖
*元數(shù)據(jù)鎖(MDL)是系統(tǒng)自動(dòng)添加的,無需手動(dòng)使用
*元數(shù)據(jù)鎖是用來防止DML與DDL起沖突的
要明白元數(shù)據(jù)鎖的作用,需要先回顧一下事務(wù)的4個(gè)隔離級別,其中mysql默認(rèn)隔離級別Repeatable Read正是靠元數(shù)據(jù)鎖來實(shí)現(xiàn)的
元數(shù)據(jù)鎖也有共享讀鎖與獨(dú)占寫鎖,二者相互排斥:
(1)當(dāng)在一個(gè)事務(wù)中對某個(gè)表進(jìn)行增刪改查(DQL、DML)時(shí),系統(tǒng)會自動(dòng)給這個(gè)表加上共享讀鎖。其他事務(wù)可以對這個(gè)表進(jìn)行增刪改查,但不能修改表結(jié)構(gòu)(DDL)
(2)當(dāng)在一個(gè)事務(wù)中對某個(gè)表進(jìn)行了修改表結(jié)構(gòu),即DDL操作(alter table ...),那么系統(tǒng)就會自動(dòng)給這個(gè)表加上獨(dú)占寫鎖,其他事務(wù)既不可對該表進(jìn)行增刪改查(DQL、DML),也不可修改表結(jié)構(gòu)(DDL)
事務(wù)提交后,元數(shù)據(jù)鎖會自動(dòng)解開
3.3意向鎖
對表進(jìn)行DML操作時(shí),系統(tǒng)會暫時(shí)給被操作的數(shù)據(jù)行加上行鎖,如果這時(shí)還要給該表加上表鎖,就會造成行鎖與表鎖的沖突(即DML自動(dòng)添加的行鎖與表鎖的沖突),為了解決這個(gè)沖突的問題,就需要使用意向鎖。
簡單來說,意向鎖是在進(jìn)行DML操作時(shí)與行鎖一起添加的,有了意向鎖后,再要添加表鎖,系統(tǒng)就會先判斷表鎖與所添加的意向鎖是否兼容,如果兼容則可以加表鎖,否則就不可。
意向鎖有2種:
(1)意向共享鎖(IS)
可由以下語句添加:
select... lock in share mode
IS與讀鎖(read)兼容,與寫鎖(write)互斥,也就是說,添加了IS后,可以對表加讀鎖,但不能加寫鎖
(2)意向排他鎖(IX)
insert語句、update語句、delete語句會自動(dòng)添加意向排他鎖,select語句可由以下語句添加:
select...for update
IX與讀鎖、寫鎖都互斥
3.4三種表級鎖總結(jié)
是否是系統(tǒng)自動(dòng)添加 | 對表的作用 | 一句話總結(jié)有啥用 | ||
元數(shù)據(jù)鎖 | 是 | 我對這張表進(jìn)行增刪改查時(shí),你也可以進(jìn)行增刪改查,但你不能更改表結(jié)構(gòu)(DDL) | 解決DDL與DML的沖突 | |
表鎖 | 讀鎖(read) | 否 | 我不能對表增刪改(DML),只能查(DQL)。 你也一樣。 | 就鎖表用的,你用你就加,不用就不加 |
寫鎖 (write) | 否 | 我可以對表增刪改查。 你都不可以 | ||
意向鎖 | 意向共享鎖(IS) | 否 | 表可以加read,不能加write | 解決DML自動(dòng)添加的行鎖與表鎖的沖突 |
意向排他鎖(IX) | 執(zhí)行增刪改時(shí)是自動(dòng),執(zhí)行查時(shí)需手動(dòng)添加 | 表read、write都不能加 |
4.行級鎖
*行級鎖:每次操作鎖住對應(yīng)的行數(shù)據(jù)。鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度最高。
*應(yīng)用在InnoDB存儲引擎中。
*由于InnoDB的數(shù)據(jù)是基于索引組織的,行鎖是通過對索引上的索引項(xiàng)加鎖來實(shí)現(xiàn)的,而不是對記錄加的鎖。
對于行級鎖,主要分為以下三類:
(1)行鎖(Record Lock):鎖定單個(gè)行記錄的鎖,防止其他事務(wù)對此行進(jìn)行update和delete。在RC、RR事務(wù)隔離級別下都支持
(2)間隙鎖(Gap Lock):鎖定索引記錄間隙(不含該記錄),確保索引記錄間隙不變,防止其他事務(wù)在這個(gè)間隙進(jìn)行insert,產(chǎn)生幻讀。在RR事務(wù)隔離級別下支持。
(3)臨鍵鎖(Next-key Lock):行鎖+間隙鎖。在RR事務(wù)隔離級別下支持。
4.1行鎖
4.1.1共享鎖與排他鎖
InnoDB實(shí)現(xiàn)了以下2種行鎖
(1)共享鎖(S):其他事務(wù)可以和當(dāng)前事務(wù)一起讀一行帶有S的數(shù)據(jù)。共享鎖之間可兼容,但與排他鎖互斥。
(2)排他鎖(X):若某行數(shù)據(jù)被加上了排他鎖,那么就只有當(dāng)前事務(wù)能操作它,其他事務(wù)不能刪改,也不能查。排他鎖之間也是互斥的
4.1.2加鎖以及查看鎖
可以看到行鎖的加鎖情況與意向共享鎖相同,也就說明二者會同時(shí)添加。
不要忘了意向共享鎖是為了解決行鎖與表鎖的沖突才設(shè)置的,因此二者才會同時(shí)添加?
*通過下圖語句可以查看系統(tǒng)內(nèi)的鎖,其中IS是意向共享鎖,
S,REC_NOT_GAP是共享鎖,S,GAP是間隙鎖,S是臨鍵鎖
4.1.3行鎖自動(dòng)升級為表鎖的情況
InnoDB行鎖是針對索引的鎖,如果對沒有索引的字段加行鎖,那么行鎖就會自動(dòng)升級為表鎖
比如在事務(wù)A中修改a字段的數(shù)據(jù)(update),同時(shí)a字段沒有索引,那么由于update操作自動(dòng)給這行數(shù)據(jù)添加了排他鎖,同時(shí)由于a字段沒有索引,這個(gè)排他鎖自動(dòng)升級為表鎖,這個(gè)表的每一行數(shù)據(jù)就都要收到排他鎖的限制,事務(wù)B不能對這個(gè)表進(jìn)行增刪改查
4.2間隙鎖與臨鍵鎖
RR隔離級別下不同索引在不同查詢情況下的加鎖類型:
非唯一索引 | 范圍查詢 | 臨鍵鎖 | ||
等值查詢 | 查詢的值存在 | 臨鍵鎖+間隙鎖 | ||
查詢的值不存在 | 間隙鎖 | |||
唯一索引 | 范圍查詢 | 行鎖+間隙鎖 | ||
等值查詢 | 查詢的值存在 | 行鎖 | ||
查詢的值不存在 | 間隙鎖 |
具體加鎖過程可見如下連接:
間隙鎖詳解https://blog.csdn.net/w15558056319/article/details/122861509?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172309730016800182785516%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=172309730016800182785516&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-23-122861509-null-null.142^v100^pc_search_result_base5&utm_term=%E9%97%B4%E9%9A%99%E9%94%81&spm=1018.2226.3001.4187