如何對網(wǎng)站的圖片做cdn萬網(wǎng)創(chuàng)始人
文章目錄
- 9.重新認識MySQL鎖
- 9.1MySQL鎖概述
- 9.2鎖分類
- 9.2.1鎖的粒度
- 9.2.2鎖的區(qū)間
- 9.2.3鎖的性能
- 9.2.4鎖的級別
- 9.3拓展:意向鎖
- 9.3.1意向鎖概述
- 9.3.2意向鎖分類
- 9.3.3意向鎖作用
- (1)意向鎖的兼容互斥性
- (2)例子1(意向鎖和表級的共享/排他鎖互斥)
- (3)例子2(意向鎖和行級的共享鎖/排他鎖兼容)
- (4)小結(jié)
9.重新認識MySQL鎖
9.1MySQL鎖概述
- 鎖是計算機協(xié)調(diào)多個進程或者線程并發(fā)訪問某一資源的機制
- 在數(shù)據(jù)庫中除了傳統(tǒng)的對計算資源的爭搶之外,數(shù)據(jù)也是供許多用戶共享的一種資源,如何保證多線程下的數(shù)據(jù)一致性是數(shù)據(jù)庫必須解決的一個問題
9.2鎖分類
共有四種角度將MySQL鎖分類:
- 鎖的粒度:
- 全局鎖
- 表級鎖
- 行級鎖
- 頁級鎖
- 鎖的區(qū)間:
- 間隙鎖
- 臨建鎖
- 鎖的性能:
- 樂觀鎖
- 悲觀鎖
- 鎖的級別:
- 共享鎖(讀鎖)
- 排他鎖(寫鎖/獨占鎖)
9.2.1鎖的粒度
- 全局鎖:鎖住數(shù)據(jù)庫中的所有表
- 表級鎖:鎖住數(shù)據(jù)庫中的整張表
- 行級鎖:鎖住對應(yīng)的行數(shù)據(jù)
9.2.2鎖的區(qū)間
-
間隙鎖
- 定義:間隙鎖用于 鎖定一個范圍(開區(qū)間) 而不是單個行。當事務(wù)在范圍內(nèi)的一行上持有鎖時,其他事務(wù)無法在這個范圍內(nèi)插入新的數(shù)據(jù),但是可以在范圍之外插入新的數(shù)據(jù)。
- 舉例:假設(shè)一個表中的索引列有序且不重復(fù),事務(wù)A持有了某個范圍內(nèi)的間隙鎖,這個范圍可能是一段索引范圍,比如(10,20),這時其他事務(wù)無法在這個范圍內(nèi)插入新的行。
-
臨建鎖
- 定義::臨建鎖是一種結(jié)合了行鎖和間隙鎖的鎖類型,它在鎖定一個范圍時同時鎖定了該范圍內(nèi)的行以及范圍之間的間隙。
- 舉例:考慮一個范圍查詢,比如查詢索引列值在(10,20)之間的行,臨建鎖會鎖定這個范圍內(nèi)的行,同時鎖定范圍之間的間隙,防止其他事務(wù)在這個范圍內(nèi)插入新的行或者改變已有行的值。
9.2.3鎖的性能
-
樂觀鎖:
-
定義:樂觀鎖認為數(shù)據(jù)在被操作時很少發(fā)生沖突,因此在訪問數(shù)據(jù)時不會立即加鎖,而是在更新數(shù)據(jù)時檢查數(shù)據(jù)是否被其他事務(wù)修改過,如果沒有則更新成功,否則進行回滾或者重試。
-
舉例:在MySQL中,可以使用樂觀鎖的方式是在更新數(shù)據(jù)時檢查數(shù)據(jù)的版本號或者時間戳是否與當前操作一致
UPDATE table_name SET column1 = value1, version = new_version WHERE id = x AND version = old_version;
-
-
悲觀鎖:
-
定義:悲觀鎖認為數(shù)據(jù)在被操作時會發(fā)生沖突,因此在訪問數(shù)據(jù)之前會先加鎖,確保其他事務(wù)無法修改該數(shù)據(jù),直到當前事務(wù)完成操作并釋放鎖。
-
舉例:在MySQL中,可以使用SELECT … FOR UPDATE語句來獲取悲觀鎖,例如
SELECT * FROM table_name WHERE condition FOR UPDATE;
-
9.2.4鎖的級別
-
共享鎖:
-
定義:共享鎖允許多個事務(wù)同時讀取同一行數(shù)據(jù),但阻止其他事務(wù)在該行上獲取排他鎖;
-
舉例:在 MySQL 中,可以使用
SELECT ... LOCK IN SHARE MODE
或者SELECT ... FOR SHARE
來獲取共享鎖,例如SELECT * FROM table_name WHERE condition LOCK IN SHARE MODE;
-
-
排他鎖:
-
定義:排他鎖(也稱為寫鎖)阻止其他事務(wù)對同一行數(shù)據(jù)進行讀取或?qū)懭氩僮?/mark>,只有獲取了排他鎖的事務(wù)才能對數(shù)據(jù)進行修改。
-
舉例:在 MySQL 中,可以使用
SELECT ... FOR UPDATE
來獲取排他鎖,例如SELECT * FROM table_name WHERE condition FOR UPDATE;
-
9.3拓展:意向鎖
9.3.1意向鎖概述
MySQL 中的意向鎖(Intention Lock)是一種用于管理表級鎖的鎖機制,用于在表級別上指示事務(wù)將要在表的哪些行上獲取鎖。
意向鎖并不是實際的鎖,而是一種指示,通常用于協(xié)調(diào)事務(wù)對表級鎖的獲取,以提高并發(fā)性能和降低死鎖的風(fēng)險。
9.3.2意向鎖分類
可分為兩種類型:意向共享鎖和意向排他鎖
-
意向共享鎖(Intention Share Lock):
- 特點:表明事務(wù)將要在表的某些行上獲取共享鎖。當一個事務(wù)打算獲取某行的共享鎖時,會在表級別請求意向共享鎖。
- 作用:意向共享鎖是為了協(xié)調(diào)多個事務(wù)同時獲取共享鎖而引入的,在獲取共享鎖之前,需要先檢查是否存在排他鎖,以防止與其他事務(wù)的排他鎖沖突。
-
意向排他鎖(Intention Exclusive Lock):
- 特點:表明事務(wù)將要在表的某些行上獲取排他鎖。當一個事務(wù)打算獲取某行的排他鎖時,會在表級別請求意向排他鎖。
- 作用:意向排他鎖是為了協(xié)調(diào)多個事務(wù)同時獲取排他鎖而引入的,在獲取排他鎖之前,需要先檢查是否存在共享鎖或其他事務(wù)的排他鎖,以防止與其他事務(wù)的共享鎖或排他鎖沖突。
9.3.3意向鎖作用
沒有意向鎖時,事務(wù)在獲取表級鎖/行級鎖之前可能需要頻繁地檢查整個表,以確定是否有其他事務(wù)已經(jīng)持有了排他鎖或共享鎖。這會增加系統(tǒng)的開銷,降低并發(fā)性能。
舉例:
事務(wù) A 獲取了某一行的排他鎖,并未提交:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
事務(wù) B 想要獲取 users
表的表鎖(共享鎖)/行級鎖:
LOCK TABLES users READ;
為共享鎖與排他鎖互斥
,所以事務(wù) B 在視圖對 users
表加共享鎖的時候,必須保證:
- 當前沒有其他事務(wù)持有 users 表的排他鎖。
- 當前沒有其他事務(wù)持有 users 表中任意一行的排他鎖 。
為了檢測是否滿足第二個條件,事務(wù) B 必須在確保 users
表不存在任何排他鎖的前提下,去檢測表中的每一行是否存在排他鎖。
很明顯這是一個效率很差的做法,但是有了意向鎖之后,情況就不一樣了:
(1)意向鎖的兼容互斥性
特點:多個事務(wù)可以對同一張表多個意向排他鎖
意向共享鎖(IS) | 意向排他鎖(IX) | |
---|---|---|
意向共享鎖(IS) | 兼容 | 兼容 |
意向排他鎖(IX) | 兼容 | 兼容 |
即意向鎖之間是互相兼容的,雖然意向鎖和自家兄弟互相兼容,但是它會與普通的排他 / 共享鎖互斥:
意向共享鎖(IS) | 意向排他鎖(IX) | |
---|---|---|
共享鎖(S) | 兼容 | 互斥 |
排他鎖(X) | 互斥 | 互斥 |
注意:這里的排他 / 共享鎖指的都是表鎖!!!
意向鎖不會與行級的共享 / 排他鎖互斥!!!
(2)例子1(意向鎖和表級的共享/排他鎖互斥)
回到剛才 users
表的例子:
事務(wù) A 獲取了某一行的排他鎖,并未提交:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
- 此時
users
表存在兩把鎖:users
表上的意向排他鎖與 id 為 6 的數(shù)據(jù)行上的排他鎖。
事務(wù) B 想要獲取 users
表的表鎖(共享鎖):
LOCK TABLES users READ;
- 此時
事務(wù) B
檢測事務(wù) A 持有users
表的意向排他鎖,就可以得知事務(wù) A
必然持有該表中某些數(shù)據(jù)行的排他鎖, - 么
事務(wù) B
對users
表的加鎖請求就會被排斥(阻塞),而無需去檢測表中的每一行數(shù)據(jù)是否存在排他鎖。
(3)例子2(意向鎖和行級的共享鎖/排他鎖兼容)
- 意向鎖并不會影響到多個事務(wù)對不同數(shù)據(jù)行加排他鎖時的并發(fā)性
事務(wù) A 獲取了某一行的排他鎖,并未提交:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
- 此時
users
表存在兩把鎖:users
表上的意向排他鎖- id 為 6 的數(shù)據(jù)行上的排他鎖。
事務(wù) B 想要獲取 users
表的表鎖(共享鎖):
LOCK TABLES users READ;
- 此時
事務(wù) B
檢測事務(wù) A 持有users
表的意向排他鎖,就可以得知事務(wù) A
必然持有該表中某些數(shù)據(jù)行的排他鎖, - 么
事務(wù) B
對users
表的加鎖請求就會被排斥(阻塞),而無需去檢測表中的每一行數(shù)據(jù)是否存在排他鎖。
最后事務(wù) C
也想獲取 users
表中某一行的排他鎖:
SELECT * FROM users WHERE id = 5 FOR UPDATE;
事務(wù) C
申請users
表的意向排他鎖。事務(wù) C
檢測到事務(wù) A
持有users
表的意向排他鎖。- 因為意向鎖之間并不互斥,所以
事務(wù) C
獲取到了users
表的意向排他鎖。 - 因為id 為 5 的數(shù)據(jù)行上不存在任何排他鎖,最終
事務(wù) C
成功獲取到了該數(shù)據(jù)行上的排他鎖。
(4)小結(jié)
意向鎖的引入主要是為了提高并發(fā)性能。通過引入意向鎖,MySQL 可以更有效地管理表級鎖,減少了在并發(fā)環(huán)境下的鎖沖突,從而提高了系統(tǒng)的并發(fā)處理能力。
在沒有意向鎖之前,如果一張表里面已經(jīng)有行鎖了,此時我們再添加表鎖,為了防止表鎖和行鎖發(fā)生沖突,表鎖就需要遍歷整個表中的數(shù)據(jù)檢查是否有行鎖。為了優(yōu)化表鎖檢索行鎖的過程,我們引入意向鎖。