偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

MySQL 核心模塊揭秘—隱式鎖

開發(fā) 前端
隱式鎖,是排他普通記錄鎖的一種特殊存在形式。我們查詢不到隱式鎖的加鎖情況,只能根據(jù)我們的經(jīng)驗(yàn)判斷記錄上是否存在隱式鎖。

1. 什么是隱式鎖?

前面我們介紹了行鎖的共享鎖、排他鎖。按照精確模式,它們又都可以細(xì)分為普通記錄鎖、間隙鎖、Next-Key 鎖。

另外,還有一種專門用于插入記錄場景的插入意向鎖。

事務(wù)讀寫記錄需要加這些行鎖時(shí),會發(fā)起加鎖操作,申請新的行鎖結(jié)構(gòu)或者復(fù)用已有的行鎖結(jié)構(gòu)。

有了對應(yīng)的行鎖結(jié)構(gòu),我們就可以通過 performance_schema.data_locks 表查詢到這些行鎖的加鎖情況了。InnoDB 內(nèi)部把這種有對應(yīng)鎖結(jié)構(gòu)的行鎖稱為顯式鎖。

隱式鎖,是相對于顯式鎖而言的,它也是一種行鎖,而且是普通記錄鎖的一種特殊存在形式。

顧名思義,既然是隱式鎖,也就意味著我們查詢不到它的加鎖情況。

我們之所以查詢不到,是因?yàn)殡[式鎖沒有對應(yīng)的行鎖結(jié)構(gòu),它就像空氣一樣,神在,形不在。

我們知道空氣是存在的,通常情況下,我們看不見,也摸不著。但是,熱空氣遇冷之后,凝結(jié)成小水珠,我們就能看得見,也能摸得著了。

我們也知道隱式鎖是存在的,卻查詢不到。它也會像空氣一樣,有被看見的時(shí)候嗎?

是的,它也有被看見的時(shí)候。但是,當(dāng)它被看見的時(shí)候,已經(jīng)換了一種形式,不再是隱式鎖了,而是變成了顯式鎖。

隱式鎖變成顯式鎖之后,我們就可以通過 performance_schema.data_locks 表查詢到加鎖情況了。

那么,問題來了,隱式鎖到底是被看見了,還是沒有被看見呢?

2. 怎么判斷存在隱式鎖?

隱式鎖,不僅可以存在于主鍵索引記錄上,還可以存在于二級索引記錄上。

在它變成顯式鎖之前,我們怎么判斷一條記錄上是否存在隱式鎖呢?

我根據(jù)代碼邏輯歸納了四種情況。

情況 1,事務(wù)執(zhí)行 insert 語句或者 update 語句插入一條記錄到主鍵索引中,事務(wù)提交之前,這條記錄上存在隱式鎖。

update 語句不是更新記錄嗎,怎么還會插入記錄?

如果你也有這樣的疑問,說明這是個(gè)好問題。

有一種場景:如果 update 語句更新了主鍵字段值,主鍵索引的原記錄會被標(biāo)記刪除,然后插入一條新記錄。

其中,原記錄的主鍵字段為更新之前的值,新記錄的主鍵字段為更新之后的值。

情況 2,事務(wù)執(zhí)行 insert 語句插入一條記錄到二級索引中,事務(wù)提交之前,這條記錄上存在隱式鎖。

情況 3,事務(wù)執(zhí)行 update 語句更新了二級索引的某個(gè)字段,二級索引的原記錄會被標(biāo)記刪除,然后插入一條新記錄,事務(wù)提交之前,原記錄和新記錄上都存在隱式鎖。

情況 4,事務(wù)執(zhí)行 delete 語句,如果掃描記錄時(shí)沒有使用二級索引,二級索引記錄不會被顯式加鎖。

二級索引記錄被標(biāo)記刪除之后,事務(wù)提交之前,記錄上都存在隱式鎖。

根據(jù)代碼邏輯歸納出所有情況是很困難的,為了幫助我們更好的判斷記錄上是否存在隱式鎖,我們有必要看看 InnoDB 代碼里的判斷邏輯長什么樣。

InnoDB 代碼里,判斷記錄上是否存在隱式鎖的邏輯,和索引類型有關(guān)。

對于主鍵索引,判斷邏輯比較簡單。

InnoDB 會從主鍵索引記錄的 DB_TRX_ID 字段中讀取事務(wù) ID,找到最后操作這條記錄的事務(wù)。

只要主鍵索引記錄上沒有顯式鎖,并且最后操作記錄的事務(wù)還沒有提交,就認(rèn)為這條記錄上存在隱式鎖。

對于二級索引,因?yàn)樗饕涗浿袥]有 DB_TRX_ID 字段,判斷邏輯會比主鍵索引復(fù)雜一點(diǎn)。

二級索引數(shù)據(jù)頁的頭信息中有個(gè) PAGE_MAX_TRX_ID 字段,表示最后修改數(shù)據(jù)頁中任意一條記錄的事務(wù) ID。

以某個(gè)二級索引中的一條記錄(S1)為例,判斷這條記錄上是否存在隱式鎖的主要步驟如下:

第 1 步,讀取 S1 所屬數(shù)據(jù)頁頭信息中的 PAGE_MAX_TRX_ID 字段,看看這個(gè)事務(wù) ID 對應(yīng)的事務(wù)是否已經(jīng)提交了。

如果事務(wù)已經(jīng)提交,說明 S1 上不存在隱式鎖。

如果事務(wù)還沒有提交,進(jìn)入第 2 步。

第 2 步,根據(jù) S1 中的主鍵字段,回表查詢對應(yīng)的主鍵索引記錄。

找到主鍵索引記錄之后,從它的 DB_TRX_ID 字段中讀取事務(wù) ID,看看這個(gè)事務(wù) ID 對應(yīng)的事務(wù)是否已經(jīng)提交了。

如果事務(wù)已經(jīng)提交,說明 S1 上不存在隱式鎖。

如果事務(wù)還沒有提交,那就麻煩了,需要進(jìn)一步判斷,這個(gè)代碼邏輯就很晦澀了。

不過,值得欣慰的是,雖然代碼邏輯很晦澀,但是用大白話描述起來可以很簡單。

用大白話描述是這樣的:只要這個(gè)還沒有提交的事務(wù)操作過 S1,不管這個(gè)操作是插入,還是刪除,都意味著 S1 上存在隱式鎖。

3. 轉(zhuǎn)換為顯式鎖

如果某條記錄上存在隱式鎖,在需要時(shí),會被轉(zhuǎn)換被顯式鎖。這個(gè)轉(zhuǎn)換主要發(fā)生在兩種場景下。

場景一,記錄(R1)上存在隱式鎖,其它事務(wù)(A)讀寫 R1 之前,如果需要對 R1 加行鎖,事務(wù) A 會把 R1 上的隱式鎖轉(zhuǎn)換為顯式鎖,然后等待 R1 上的行鎖被釋放之后,事務(wù) A 才能獲得鎖。

場景二,某個(gè)事務(wù)部分回滾時(shí),如果它操作過的記錄上存在隱式鎖,會被轉(zhuǎn)換為顯式鎖。

部分回滾,指的是把事務(wù)回滾到某個(gè)保存點(diǎn)。這個(gè)保存點(diǎn)可以是我們手動創(chuàng)建的保存點(diǎn),也可以是 InnoDB 內(nèi)部創(chuàng)建的保存點(diǎn)。

InnoDB 內(nèi)部創(chuàng)建的保存點(diǎn),主要用于插入記錄出現(xiàn)沖突時(shí),回滾已經(jīng)執(zhí)行的操作。

介紹完隱式鎖轉(zhuǎn)換為顯式鎖的場景,我們再來看看隱式鎖會被轉(zhuǎn)換成什么樣的顯式鎖。

前面我們介紹過,隱式鎖是普通記錄鎖的一種特殊存在形式,所以,它也是普通記錄鎖。

隱式鎖,既可以存在于剛剛插入的記錄上,也可以存在于標(biāo)記刪除的二級索引記錄上,所以,它又是一種排他鎖。

兩者綜合起來,隱式鎖本質(zhì)上相當(dāng)于排他普通記錄鎖。

發(fā)生轉(zhuǎn)換時(shí),隱式鎖會被轉(zhuǎn)換為排他普通記錄鎖。這個(gè)轉(zhuǎn)換邏輯是不是又簡單又粗暴?

4. 總結(jié)

隱式鎖,是排他普通記錄鎖的一種特殊存在形式。

我們查詢不到隱式鎖的加鎖情況,只能根據(jù)我們的經(jīng)驗(yàn)判斷記錄上是否存在隱式鎖。

在某些場景下,隱式鎖會被轉(zhuǎn)換為顯式鎖,然后,我們就可以通過 performance_schema.data_locks 表查詢到加鎖情況了。

責(zé)任編輯:武曉燕 來源: 愛可生開源社區(qū)
相關(guān)推薦

2024-04-03 08:20:53

MySQL核心模塊

2024-06-05 11:49:33

2024-05-15 09:05:42

MySQL核心模塊

2024-08-07 14:58:00

MySQL釋放鎖核心模塊

2024-10-30 10:38:08

2024-10-16 11:11:51

隔離InnoDB死鎖

2024-09-04 08:44:18

MySQL核心模塊

2024-03-27 13:33:00

MySQLInnoDB事務(wù)

2024-05-29 10:17:01

2025-02-26 08:26:38

2010-11-16 15:11:52

Oracle隱式游標(biāo)

2024-11-05 10:52:07

2017-12-20 14:14:16

數(shù)據(jù)庫MySQL數(shù)據(jù)類型

2022-02-23 21:24:21

索引SQL字符

2024-07-29 09:57:47

2023-12-12 08:50:22

MySQL隱式轉(zhuǎn)換varchar

2010-01-26 14:04:02

2009-09-01 10:49:28

C#具有隱式類型聲明

2009-09-04 10:49:19

C#隱式轉(zhuǎn)換

2009-09-11 10:07:05

Linq隱式類型化局部
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號