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

繼續(xù)深入數(shù)據(jù)庫(kù) 了解一下數(shù)據(jù)庫(kù)的鎖機(jī)制

數(shù)據(jù)庫(kù)
我們?cè)诟卟l(fā)的場(chǎng)景下,經(jīng)常會(huì)在異常日志中看到“dead lock(死鎖)”的錯(cuò)誤信息。想了無(wú)數(shù)的解決方案,都沒(méi)有能夠最終的解決,到底是什么原因引起了死鎖呢?要解決這個(gè)問(wèn)題,我們就必須先了解透徹?cái)?shù)據(jù)庫(kù)都有哪些鎖?他們的工作機(jī)制是什么樣的。

我們?cè)诟卟l(fā)的場(chǎng)景下,經(jīng)常會(huì)在異常日志中看到“dead lock(死鎖)”的錯(cuò)誤信息。想了無(wú)數(shù)的解決方案,都沒(méi)有能夠最終的解決,到底是什么原因引起了死鎖呢?要解決這個(gè)問(wèn)題,我們就必須先了解透徹?cái)?shù)據(jù)庫(kù)都有哪些鎖?他們的工作機(jī)制是什么樣的。

那,讓我們開(kāi)啟今天的學(xué)習(xí)之路吧。

為什么數(shù)據(jù)庫(kù)要加鎖?

 

[[246315]]

 

當(dāng)多條請(qǐng)求并發(fā)訪問(wèn)一個(gè)數(shù)據(jù)庫(kù)資源時(shí),有可能就會(huì)導(dǎo)致數(shù)據(jù)的不一致,因此,就需要一種機(jī)制來(lái)將數(shù)據(jù)庫(kù)的訪問(wèn)順序化,從而保證數(shù)據(jù)庫(kù)數(shù)據(jù)的一致性,這個(gè)我們?cè)?/p>

《數(shù)據(jù)庫(kù)常用的事務(wù)隔離級(jí)別都有哪些?都是什么原理?》也有講到。事務(wù)就是就是一種順序化的機(jī)制,而事務(wù)要達(dá)到目的,就必須要有所的支持。

 

[[246316]]

 

數(shù)據(jù)庫(kù)都有哪些鎖?

由于數(shù)據(jù)庫(kù)的種類也不少,每種數(shù)據(jù)庫(kù)的鎖大致都相同,但是細(xì)節(jié)上略有不同,因此,我們就選擇MySql/InnoDB作為講解的對(duì)象。

InnoDB按照鎖的類型來(lái)劃分,主要分為了三個(gè)大類:共享鎖(Shared lock)、排它鎖,也叫獨(dú)占鎖(Exclusive Locks)、意向鎖(Intent Locks)。其中,意向鎖又分為了意向共享和意向排他,因此,嚴(yán)格意義上來(lái)說(shuō),是有四種分類的鎖,分別是:

  1. 共享鎖(Shared lock),簡(jiǎn)稱:S鎖
  2. 排它鎖(Exclusive Locks),簡(jiǎn)稱:X鎖
  3. 意向共享鎖(Intent Shared lock),簡(jiǎn)稱:IS鎖
  4. 意向排他鎖(Intent Exclusive Locks),簡(jiǎn)稱:IX鎖

接下來(lái),我們就聊聊這些鎖都是怎么工作的。

 

[[246317]]

 

共享鎖

共享鎖,顧名思義,就是我雖然鎖住了這個(gè)資源,但是我并不會(huì)獨(dú)占它,我同樣允許其他人使用這個(gè)資源。

 

[[246318]]

 

通常情況下,查詢就是使用的共享鎖。

例如:

事務(wù)A先執(zhí)行了一個(gè)查詢

 

  1. select * from table

事務(wù)A還沒(méi)有執(zhí)行完,事務(wù)B就執(zhí)行了另一個(gè)查詢

 

  1. select * from table where id = 1; 

這個(gè)時(shí)候,事務(wù)B是可以優(yōu)先于事務(wù)A完成他的查詢的,并不存在必須要事務(wù)A結(jié)束,才執(zhí)行事務(wù)B的情況,這就是共享鎖的作用。

排它鎖

排它鎖,又叫獨(dú)占鎖,顧名思義,我鎖住了,這東西就是我一個(gè)人的,誰(shuí)也別想看,別想碰。

通常情況下,修改操作就是使用的排它鎖。

 

[[246319]]

 

例如:

事務(wù)A先執(zhí)行了一個(gè)修改操作

 

  1. update table set Status = 1; 

事務(wù)B還事務(wù)A沒(méi)有完成時(shí),執(zhí)行了另一個(gè)修改操作

 

  1. update table set Status = 0 where id =1; 

這個(gè)時(shí)候,事務(wù)B就只有等著,到事務(wù)A執(zhí)行完成以后,事務(wù)B才能夠繼續(xù),這就是排它鎖的作用。

意向鎖

共享鎖、排它鎖按照其作用的粒度,可以鎖到行級(jí),也可以鎖到頁(yè)級(jí)或表級(jí)。不過(guò)意向鎖只作用于表級(jí),主要是用來(lái)標(biāo)記一個(gè)事務(wù)對(duì)于這張表操作的一個(gè)意向。

例如:我有一個(gè)事務(wù)需要使用表鎖,那我就需要知道,這個(gè)表是否存在其他的鎖,如果有,可能我就需要等待。但是,我如果要排除其他鎖,我就需要一個(gè)一個(gè)記錄的遍歷,才知道是不是存在行鎖。因此,數(shù)據(jù)庫(kù)對(duì)于行鎖就提出另一個(gè)機(jī)制,就是意向鎖,如果你要對(duì)這個(gè)表進(jìn)行行鎖時(shí),那么先在表上加一個(gè)意向鎖,方便其他事務(wù)查詢。

 

[[246320]]

 

因此,意向鎖就有了以下協(xié)議:

  • 一個(gè)事務(wù)獲得表t中某行的S鎖之前,必須先獲得t表上的IS鎖或者更強(qiáng)類型的鎖。
  • 一個(gè)事務(wù)獲得表t中某行的X鎖之前, 必須先獲得t表上的IX鎖。

現(xiàn)在我們知道了所的類型,接下來(lái)我們說(shuō)說(shuō)鎖的級(jí)別。

 

[[246321]]

 

根據(jù)鎖的顆?;蛘呒?jí)別不同,我們又把所分為了三個(gè)級(jí)別:表鎖(table-level locking)、頁(yè)鎖(page-level locking)、行鎖(row-level locking)。

MyISAM和MEMORY存儲(chǔ)引擎采用的是表鎖(table-level locking);BDB存儲(chǔ)引擎采用的是頁(yè)鎖(page-level locking),但也支持表鎖;InnoDB存儲(chǔ)引擎既支持行鎖(row-level locking),也支持表鎖,但默認(rèn)情況下是采用行鎖。

而行鎖又包括了三種行鎖的算法,分別是:

  1. 記錄鎖(Record Lock)
  2. 間隙鎖(Gap Lock)
  3. 臨鍵鎖(Next-Key Lock)

這里有個(gè)小知識(shí)點(diǎn):InnoDB的行鎖只針對(duì)索引項(xiàng)使用,也就是說(shuō),只有在通過(guò)索引檢索數(shù)據(jù)時(shí),InnoDB才使用行鎖,其他時(shí)候都是使用的表鎖。

記錄鎖(Record Locks)

記錄鎖,顧名思義,就是鎖住一條記錄。這是Read Committed(讀提交)事務(wù)級(jí)別的默認(rèn)鎖級(jí)別。

記錄鎖是作用于索引的,所以,當(dāng)查詢不是作用于索引上時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)隱式的聚集索引,然后作用在索引上。

例如:

 

  1. select * from table where id = 1 lock in share mode; 

就是一個(gè)共享記錄鎖,

 

  1. select * from table for update where id = 1 ; 

就是一個(gè)排他記錄鎖。

間隙鎖(Gap Lock)

間隙鎖,它不會(huì)去鎖住索引本身,但是會(huì)鎖住的是一個(gè)索引的范圍。啟用它有一個(gè)前置條件,就是數(shù)據(jù)庫(kù)隔離級(jí)別必須是Repeatable Read(可重復(fù)讀),這也是InnoDB的默認(rèn)隔離級(jí)別,假設(shè)我們將隔離級(jí)別降到Read Committed(讀提交),間隙鎖將會(huì)自動(dòng)失效。

間隙鎖的使用,能夠有效的防止幻讀。

例如:

如果事務(wù)A執(zhí)行了

 

  1. select * from table where id between 8 and 15 for update

這是,事務(wù)B想在事務(wù)A執(zhí)行期間執(zhí)行插入一條id是10的記錄,就會(huì)被阻止。因?yàn)檫@會(huì)導(dǎo)致事務(wù)A中的多次查詢數(shù)據(jù)不一致。

臨鍵鎖(Next-Key Lock)

臨鍵鎖就是記錄鎖+間隙鎖的組合方式。這是Repeatable Read(可重復(fù)讀)隔離級(jí)別的默認(rèn)鎖級(jí)別。使用臨鍵鎖有一個(gè)好處,就是,假設(shè)我們執(zhí)行執(zhí)行一個(gè)查詢

 

  1. select * from table where id = 100; 

如果id是***索引,那么臨鍵鎖就會(huì)降級(jí)為記錄鎖,鎖住這條記錄,而不是去鎖住一個(gè)范圍。

我們講完了這些鎖,那么就不禁要問(wèn)了,死鎖是怎么產(chǎn)生的呢?

這就要說(shuō)到另一個(gè)情況,就是鎖的升級(jí)。

鎖的升級(jí)

 

[[246322]]

 

假設(shè),我們先進(jìn)行了一個(gè)查詢,找到了目標(biāo)數(shù)據(jù),然后進(jìn)行修改,在這個(gè)事務(wù)中,其實(shí)不同的階段,鎖的類型是不同的。

當(dāng)我們進(jìn)行查詢的時(shí)候,我們想數(shù)據(jù)庫(kù)先獲得了一個(gè)共享鎖,當(dāng)我們要對(duì)這條數(shù)據(jù)進(jìn)行更新的時(shí)候,并不是釋放共享鎖,然后再獲取排它鎖,而是進(jìn)行了一個(gè)鎖的升級(jí)操作,直接將共享鎖升級(jí)成為了排它鎖。

而就是因?yàn)檫@個(gè)操作,可能導(dǎo)致了死鎖。

死鎖

 

[[246323]]

 

假設(shè):事務(wù)A中有一個(gè)鎖升級(jí)操作,也就是先執(zhí)行

 

  1. select * from table where id =1 

再執(zhí)行

 

  1. update table set Status = 1 where id =1 

事務(wù)B中,同樣存在這樣的情況,先執(zhí)行

 

  1. select * from table where id =1 

再執(zhí)行

 

  1. update table set Name = '牛' where id =1 

而執(zhí)行的順序恰好是:

  1. 事務(wù)A獲得了共享鎖,執(zhí)行查詢;
  2. 事務(wù)B獲得了共享鎖,執(zhí)行查詢;
  3. 事務(wù)A需要升級(jí)排它鎖,執(zhí)行修改;
  4. 事務(wù)B也需要升級(jí)排它鎖,不能釋放共享鎖。

于是,死鎖就發(fā)生了。當(dāng)然,還有一種交叉死鎖的情況,更為常見(jiàn),大家可以自己百度看看了。

死鎖發(fā)生時(shí),數(shù)據(jù)庫(kù)并不會(huì)直接檢查到死鎖的存在,只有在鎖等待超時(shí)的時(shí)候被發(fā)現(xiàn),然后殺死其中一個(gè)請(qǐng)求。如果并發(fā)量高時(shí),死鎖就會(huì)引起大量的線程掛起,占用大量資源。

怎么預(yù)防死鎖呢?

最直接的辦法就是,別在update前先select一次。

但是,這種情況在所難免,很多時(shí)候我們update時(shí),都是需要先select一次的,如果所有地方要求不能select,那代碼難度勢(shì)必就幾何級(jí)的上升。

還有一種辦法就是,加硬件,提高并發(fā)能力,這樣,出現(xiàn)兩次事務(wù)同時(shí)請(qǐng)求的概率就下降了。不過(guò),這個(gè)方式成本太高。

當(dāng)然,我們還可以直接在查詢時(shí),就申請(qǐng)到最終事務(wù)需要的鎖級(jí)別,避免升級(jí)鎖的出現(xiàn),也可以預(yù)防死鎖,例如查詢時(shí)就直接寫(xiě)

 

  1. select * from table for update;  
責(zé)任編輯:龐桂玉 來(lái)源: 今日頭條
相關(guān)推薦

2021-01-21 10:23:43

數(shù)據(jù)庫(kù)架構(gòu)技術(shù)

2022-03-24 13:36:18

Java悲觀鎖樂(lè)觀鎖

2010-06-07 13:30:15

2013-09-13 09:31:09

MongoDBZardosht KaTokutek

2011-03-30 13:44:45

MySQL數(shù)據(jù)庫(kù)鎖機(jī)制

2011-08-03 15:14:17

Excel XP數(shù)據(jù)庫(kù)功能

2010-09-27 14:15:59

SQL數(shù)據(jù)庫(kù)角色

2010-11-29 14:06:42

Sybase數(shù)據(jù)庫(kù)日志

2021-09-15 09:51:36

數(shù)據(jù)庫(kù)架構(gòu)技術(shù)

2010-12-29 09:50:06

數(shù)據(jù)庫(kù)安全審計(jì)數(shù)據(jù)庫(kù)審計(jì)

2011-03-25 14:07:12

IBMDB2數(shù)據(jù)庫(kù)數(shù)據(jù)移動(dòng)

2019-12-12 14:52:10

數(shù)據(jù)庫(kù)腳本

2024-12-16 00:52:26

MySQL數(shù)據(jù)庫(kù)并發(fā)

2010-11-08 10:16:41

SQL Server數(shù)

2022-07-28 09:02:41

文件存儲(chǔ)系統(tǒng)

2011-08-05 09:33:56

OracleUser ProcesServer Proc

2011-07-20 17:31:36

關(guān)系型數(shù)據(jù)庫(kù)

2018-02-27 15:48:31

數(shù)據(jù)庫(kù)SQL鎖死

2023-01-12 17:18:06

數(shù)據(jù)庫(kù)多云

2010-11-29 11:22:36

SYBASE數(shù)據(jù)庫(kù)日志
點(diǎn)贊
收藏

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