日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 架構(gòu)師社區(qū)
[導(dǎo)讀]最全整理,值得收藏!

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖

來(lái)源 | 悟空聊架構(gòu)(ID:PassJava666)


本篇主要內(nèi)容如下:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 本篇主要內(nèi)容

一、事務(wù)

1.1 什么是事務(wù)

為單個(gè)工作單元而執(zhí)行的一系列操作。如查詢(xún)、修改數(shù)據(jù)、修改數(shù)據(jù)定義。

1.2 語(yǔ)法

「(1)顯示定義事務(wù)的開(kāi)始、提交」

BEGIN`?`TRAN``INSERT`?`INTO`?`b(t1)?``VALUES``(1)``INSERT`?`INTO`?`b(t1)?``VALUES``(2)``COMMIT`?`TRAN

「(2)隱式定義」

如果不顯示定義事務(wù)的邊界,則SQL Server會(huì)默認(rèn)把每個(gè)單獨(dú)的語(yǔ)句作為一個(gè)事務(wù),即在執(zhí)行完每個(gè)語(yǔ)句之后就會(huì)自動(dòng)提交事務(wù)。

1.3 事務(wù)的四個(gè)屬性ACID

「(1)原子性Atomicity」

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 原子性Atomicity**
  • 1.事務(wù)必須是原子工作單元。事務(wù)中進(jìn)行的修改,要么全部執(zhí)行,要么全都不執(zhí)行;

  • 2.在事務(wù)完成之前(提交指令被記錄到事務(wù)日志之前),系統(tǒng)出現(xiàn)故障或重新啟動(dòng),SQL Server將會(huì)撤銷(xiāo)在事務(wù)中進(jìn)行的所有修改;

  • 3.事務(wù)在處理中遇到錯(cuò)誤,SQL Server通常會(huì)自動(dòng)回滾事務(wù);

  • 4.少數(shù)不太嚴(yán)重的錯(cuò)誤不會(huì)引發(fā)事務(wù)的自動(dòng)回滾,如主鍵沖突、鎖超時(shí)等;

  • 5.可以使用錯(cuò)誤處理來(lái)捕獲第4點(diǎn)提到的錯(cuò)誤,并采取某種操作,如把錯(cuò)誤記錄在日志中,再回滾事務(wù);

  • 6.SELECT @@TRANCOUNT可用在代碼的任何位置來(lái)判斷當(dāng)前使用SELECT @@TRANCOUNT的地方是否位于一個(gè)打開(kāi)的事務(wù)當(dāng)中,如果不在任何打開(kāi)的事務(wù)范圍內(nèi),則該函數(shù)返回0;如果在某個(gè)打開(kāi)的事務(wù)返回范圍內(nèi),則返回一個(gè)大于0的值。打開(kāi)一個(gè)事務(wù),@@TRANCOUNT=@@TRANCOUNT+1;提交一個(gè)事務(wù),@@TRANCOUNT-1。

「(2)一致性Consiitency」

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 一致性Consiitency
  • 1.同時(shí)發(fā)生的事務(wù)在修改和查詢(xún)數(shù)據(jù)時(shí)不發(fā)生沖突;

  • 2.一致性取決于應(yīng)用程序的需要。后面會(huì)講到一致性級(jí)別,以及如何對(duì)一致性進(jìn)行控制。

「(3)隔離性Isolation」

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 隔離性Isolation
  • 1.用于控制數(shù)據(jù)訪(fǎng)問(wèn),確保事務(wù)只訪(fǎng)問(wèn)處于期望的一致性級(jí)別下的數(shù)據(jù);

  • 2.使用鎖對(duì)各個(gè)事務(wù)之間正在修改和查詢(xún)的數(shù)據(jù)進(jìn)行隔離。

「(4)持久性Durability」

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 持久性Durability
  • 1.「寫(xiě)事務(wù)日志:」 在將數(shù)據(jù)修改寫(xiě)入到磁盤(pán)上數(shù)據(jù)庫(kù)的數(shù)據(jù)分區(qū)之前會(huì)把這些修改寫(xiě)入到磁盤(pán)上數(shù)據(jù)庫(kù)的事務(wù)日志中,把提交指令記錄到磁盤(pán)的事務(wù)日志中以后,即時(shí)數(shù)據(jù)修改還沒(méi)有應(yīng)用到磁盤(pán)的數(shù)據(jù)分區(qū),也可以認(rèn)為事務(wù)是持久化的。

  • 2.「系統(tǒng)重新啟動(dòng):」 正常啟動(dòng)或在發(fā)生系統(tǒng)故障之后啟動(dòng),SQL Server會(huì)每個(gè)數(shù)據(jù)庫(kù)的事務(wù)日志,進(jìn)行回復(fù)處理。

  • 3.「恢復(fù)處理包含兩個(gè)階段:」 重做階段和撤銷(xiāo)階段。

  • 4.「前滾:」 在重做階段,對(duì)于提交指令已經(jīng)寫(xiě)入到日志的事務(wù),但數(shù)據(jù)修改還沒(méi)有應(yīng)用到數(shù)據(jù)分區(qū)的事務(wù),數(shù)據(jù)庫(kù)引擎會(huì)重做這些食物所做的所有修改。

  • 5.「回滾:」 在撤銷(xiāo)階段,對(duì)于提交指令沒(méi)有寫(xiě)入到日志中的事務(wù),數(shù)據(jù)庫(kù)引擎會(huì)撤銷(xiāo)這些事務(wù)所做的修改。(這句話(huà)需要research,可能是不正確的。因?yàn)樘峤恢噶顩](méi)有寫(xiě)入到數(shù)據(jù)分區(qū),撤銷(xiāo)修改是指撤銷(xiāo)哪些修改呢?)

二、鎖

2.1 事務(wù)中的鎖

(1)SQL Server使用鎖來(lái)實(shí)現(xiàn)事務(wù)的隔離。

(2)事務(wù)獲取鎖這種控制資源,用于保護(hù)數(shù)據(jù)資源,防止其他事務(wù)對(duì)數(shù)據(jù)進(jìn)行沖突的或不兼容的訪(fǎng)問(wèn)。

2.2 鎖模式

「(1)排他鎖」8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖

排他鎖
  • a.當(dāng)試圖修改數(shù)據(jù)時(shí),事務(wù)只能為所依賴(lài)的數(shù)據(jù)資源請(qǐng)求排他鎖。

  • b.持有排他鎖時(shí)間:一旦某個(gè)事務(wù)得到了排他鎖,則這個(gè)事務(wù)將一直持有排他鎖直到事務(wù)完成。

  • c.排他鎖和其他任何類(lèi)型的鎖在多事務(wù)中不能在同一階段作用于同一個(gè)資源。

如:當(dāng)前事務(wù)獲得了某個(gè)資源的排他鎖,則其他事務(wù)不能獲得該資源的任何其他類(lèi)型的鎖。其他事務(wù)獲得了某個(gè)資源的任何其他類(lèi)型的鎖,則當(dāng)前事務(wù)不能獲得該資源的排他鎖。

「(2)共享鎖」8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖

共享鎖
  • a.當(dāng)試圖讀取數(shù)據(jù)時(shí),事務(wù)默認(rèn)會(huì)為所依賴(lài)的數(shù)據(jù)資源請(qǐng)求共享鎖。
  • b.持有共享鎖時(shí)間:從事務(wù)得到共享鎖到讀操作完成。
  • c.多個(gè)事務(wù)可以在同一階段用共享鎖作用于同一數(shù)據(jù)資源。
  • d.在讀取數(shù)據(jù)時(shí),可以對(duì)如何處理鎖定進(jìn)行控制。后面隔離級(jí)別會(huì)講到如何對(duì)鎖定進(jìn)行控制。

2.3 排他鎖和共享鎖的兼容性

(1)如果數(shù)據(jù)正在由一個(gè)事務(wù)進(jìn)行修改,則其他事務(wù)既不能修改該數(shù)據(jù),也不能讀?。ㄖ辽倌J(rèn)不能)該數(shù)據(jù),直到第一個(gè)事務(wù)完成。

(2)如果數(shù)據(jù)正在由一個(gè)事務(wù)讀取,則其他事務(wù)不能修改該數(shù)據(jù)(至少默認(rèn)不能)。

2.4 可鎖定的資源的類(lèi)型

RID、KEY(行)、PAGE(頁(yè))、對(duì)象(例如表)、數(shù)據(jù)庫(kù)、EXTENT(區(qū))、分配單元(ALLOCATION_UNIT)、堆(HEAP)、以及B樹(shù)(B-tree)。

「RID: 標(biāo)識(shí)頁(yè)上的特定行」

  • 格式: fileid: pagenumber: rid (1:109:0 )

其中fileid標(biāo)識(shí)包含頁(yè)的文件, pagenumber標(biāo)識(shí)包含行的頁(yè),rid標(biāo)識(shí)頁(yè)上的特定行。

fileid與sys.databases_files 目錄視圖中的file_id列相匹配

  • 例子:

在查詢(xún)視圖sys.dm_tran_locks的時(shí)候有一行的resource_description列顯示RID 是1:109:0 而status列顯示wait,

表示第1個(gè)數(shù)據(jù)文件上的第109頁(yè)上的第0行上的鎖資源。

2.5 鎖升級(jí)

SQL Server可以先獲得細(xì)粒度的鎖(例如行或頁(yè)),在某些情況下將細(xì)粒度鎖升級(jí)為更粗粒度的鎖(例如,表)。
例如單個(gè)語(yǔ)句獲得至少5000個(gè)鎖,就會(huì)觸發(fā)鎖升級(jí),如果由于鎖沖突而導(dǎo)致無(wú)法升級(jí)鎖,則SQL Server每當(dāng)獲取1250個(gè)新鎖時(shí)出發(fā)鎖升級(jí)。

三、阻塞

3.1 阻塞

當(dāng)多個(gè)事務(wù)都需要對(duì)某一資源進(jìn)行鎖定時(shí),默認(rèn)情況下會(huì)發(fā)生阻塞。被阻塞的請(qǐng)求會(huì)一直等待,直到原來(lái)的事務(wù)釋放相關(guān)的鎖。鎖定超時(shí)期限可以限制,這樣就可以限制被阻塞的請(qǐng)求在超時(shí)之前要等待的時(shí)間。

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 阻塞
  • 階段1:事務(wù)A請(qǐng)求資源S1,事務(wù)不對(duì)資源S1進(jìn)行操作

  • 階段2:事務(wù)A用鎖A鎖定資源S1,事務(wù)B請(qǐng)求對(duì)資源S1進(jìn)行不兼容的鎖定(鎖B),鎖B的請(qǐng)求被阻塞,事務(wù)B將進(jìn)入等待狀態(tài)

  • 階段3:事務(wù)A正在釋放鎖A,事務(wù)B等待鎖A釋放,

  • 階段4:事務(wù)A的鎖A已釋放,事務(wù)B用鎖B鎖定資源S1

3.2 排除阻塞問(wèn)題

例子:

3.2.1 準(zhǔn)備工作:

  • 1.準(zhǔn)備測(cè)試數(shù)據(jù)
--先創(chuàng)建一張表Product作為測(cè)試。id為表的主鍵,price為product的價(jià)格
CREATE?TABLE?[dbo].[myProduct](
????[id]?[int]?NOT?NULL,
????[price]?[money]?NOT?NULL
)?ON?[PRIMARY]
GO
--插入一條數(shù)據(jù),id=1,price=10
INSERT?INTO?[TSQLFundamentals2008].[dbo].[myProduct]([id],[price])VALUES(1,10)
  • 2.模擬阻塞發(fā)生的情況

在SQL Server中打開(kāi)三個(gè)查詢(xún)窗口Connection1、Connection2、Connection3,分別按順序執(zhí)行表格中的執(zhí)行語(yǔ)句。

--Connection1 BEGIN TRAN UPDATE dbo.myProduct SET price?=?price?+ 1 WHERE id=1 
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 Connection1結(jié)果

「結(jié)論1:」

為了更新id=1這一行數(shù)據(jù),會(huì)話(huà)必須先獲得一個(gè)排他鎖。事務(wù)處于一直打開(kāi)狀態(tài),沒(méi)有提交,所以事務(wù)一直持有排他鎖,直到事務(wù)提交并完成。

--Connection2 SELECT * FROM dbo.myProduct WHERE id=1 
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 Connection2結(jié)果

「結(jié)論2:」

事務(wù)為了讀取數(shù)據(jù),需要請(qǐng)求一個(gè)共享鎖,但是這一行已經(jīng)被其他會(huì)話(huà)持有的排他鎖鎖定,而且共享鎖和排他鎖不是兼容的,所以會(huì)話(huà)被阻塞,進(jìn)入等待狀態(tài)

--Connection3 SELECT request_session_id AS 會(huì)話(huà)id ,
????????resource_type AS 請(qǐng)求鎖定的資源類(lèi)型?,
????????resource_description AS 描述?,
????????request_mode AS 模式?,
????????request_status AS 狀態(tài) FROM sys.dm_tran_locks
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 Connection3查詢(xún)結(jié)果

「結(jié)論3:」

「會(huì)話(huà)56:」(1)狀態(tài)WAIT-等待鎖

(2)正在等待第1個(gè)數(shù)據(jù)文件上的第109頁(yè)上的第0行資源的共享鎖

(3)持有第1個(gè)數(shù)據(jù)文件上的第109頁(yè)資源的意向共享鎖

(3)持有OBJECT資源,意向共享鎖

(4)持有DATABASE資源,意向共享鎖

「會(huì)話(huà)52:」

(1)狀態(tài)WAIT-授予鎖

(2)正在等待第1個(gè)數(shù)據(jù)文件上的第109頁(yè)上的第0行資源的排他鎖(3)持有第1個(gè)數(shù)據(jù)文件上的第109頁(yè)資源的排他鎖

(3)持有OBJECT資源,排他鎖

(4)持有DATABASE資源,排他鎖

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

3.2.2 分析阻塞原因

3.2.2.1 sys.dm_tran_locks 視圖

(1)該動(dòng)態(tài)視圖可以查詢(xún)出哪些資源被哪個(gè)進(jìn)程ID鎖了

(2)查詢(xún)出對(duì)資源授予或正在等待的鎖模式

(3)查詢(xún)出被鎖定資源的類(lèi)型

上面的查詢(xún)語(yǔ)句3已經(jīng)用到了這個(gè)視圖,可以參考上圖中的分析說(shuō)明。

3.2.2.2 sys.dm_exec_connections 視圖

(1)查詢(xún)出該動(dòng)態(tài)視圖可以查詢(xún)出進(jìn)程相關(guān)的信息

(2)查詢(xún)出最后一次發(fā)生讀操作和寫(xiě)操作的時(shí)間last_read,last_write

(3)查詢(xún)出進(jìn)程執(zhí)行的最后一個(gè)SQL批處理的二進(jìn)制標(biāo)記most_recent_sql_handle

SELECT session_id?, connect_time ,
????????last_read?,
????????last_write?,
????????most_recent_sql_handle FROM sys.dm_exec_connections WHERE session_id IN ( 52, 56 )
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 查詢(xún)結(jié)果18000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 查詢(xún)結(jié)果2

「結(jié)論:」

「會(huì)話(huà)52:」

(1)connect_time連接時(shí)間:2016-06-07 07:09:41.103

(2)last_read最后一次讀操作時(shí)間:2016-06-07 07:10:56.233

(3)last_write最后一次寫(xiě)操作時(shí)間:2016-06-07 07:10:57.873

(4)most_recent_sql_handle這是一個(gè)二進(jìn)制標(biāo)記,最后一個(gè)SQL批處理

「會(huì)話(huà)56:」

(1)狀態(tài)WAIT-授予鎖

(2)正在等待第1個(gè)數(shù)據(jù)文件上的第109頁(yè)上的第0行資源的排他鎖(3)持有第1個(gè)數(shù)據(jù)文件上的第109頁(yè)資源的排他鎖

(3)持有OBJECT資源,排他鎖

(4)持有DATABASE資源,排他鎖

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

3.2.2.3 sys.dm_exec_sql_text 表函數(shù)

示例:

會(huì)話(huà)52:
執(zhí)行的SQL語(yǔ)句:
BEGIN?TRAN
UPDATE?dbo.myProduct
SET?price?=?price?+?1
WHERE?id?=?1

會(huì)話(huà)56:
執(zhí)行的SQL語(yǔ)句:
(@1?tinyint)
SELECT?*?FROM?[dbo].[myProduct]
WHERE?[id]=@1

(1)該函數(shù)可以將二進(jìn)制標(biāo)記most_recent_sql_handle作為參數(shù),然后返回SQL代碼。

(2)阻塞進(jìn)程在不斷地運(yùn)行,所以在代碼中看到的最后一個(gè)操作不一定是導(dǎo)致問(wèn)題的語(yǔ)句。在本例中最后一條執(zhí)行語(yǔ)句是導(dǎo)致阻塞的語(yǔ)句。

SELECT session_id?, text FROM sys.dm_exec_connections CROSS APPLY sys.dm_exec_sql_text
????????(most_recent_sql_handle) AS ST WHERE session_id IN ( 52, 56 )
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 查詢(xún)結(jié)果

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

3.2.2.4 sys.dm_exec_sessions 視圖

(1)會(huì)話(huà)建立的時(shí)間login_time

(2)特定于會(huì)話(huà)的客戶(hù)端工作站名稱(chēng)host_name

(3)初始化會(huì)話(huà)的客戶(hù)端程序的名稱(chēng)program_name

(4)會(huì)話(huà)所使用的SQL Server登錄名login_name

(5)最近一次會(huì)話(huà)請(qǐng)求的開(kāi)始時(shí)間last_request_start_time

(6)最近一次會(huì)話(huà)請(qǐng)求的完成時(shí)間last_request_end_time

SELECT * FROM sys.dm_exec_sessions
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 查詢(xún)結(jié)果

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

3.2.2.5 sys.dm_exec_requests 視圖

(1)識(shí)別出阻塞鏈涉及到的會(huì)話(huà)、爭(zhēng)用的資源、被阻塞會(huì)話(huà)等待了多長(zhǎng)時(shí)間

SELECT * FROM sys.dm_exec_sessions
8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 查詢(xún)結(jié)果18000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 查詢(xún)結(jié)果2

「結(jié)論:」

「會(huì)話(huà)56:」

(1)被會(huì)話(huà)52阻塞,blocking_session_id = 52

(2)會(huì)話(huà)52的開(kāi)始時(shí)間start_time

(3)狀態(tài)掛起status = suspended

(4)掛起的命令command

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

3.2.3 解決阻塞問(wèn)題

3.2.3.1 Lock_TIMEOUT 選項(xiàng)

(1)設(shè)置會(huì)話(huà)等待鎖釋放的超時(shí)期限

(2)默認(rèn)情況下會(huì)話(huà)不會(huì)設(shè)置等待鎖釋放的超時(shí)期限

(3)設(shè)置會(huì)話(huà)超時(shí)期限為5秒, SET Lock_TIMEOUT 5000

(4)鎖定如果超時(shí),不會(huì)引發(fā)事務(wù)回滾

(5)取消會(huì)話(huà)超時(shí)鎖定的設(shè)置,SET LOCK_TIMEOUT -1

如果超時(shí),將顯示以下錯(cuò)誤:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 錯(cuò)誤提示

3.2.3.1 KILL命令

(1)殺掉會(huì)話(huà)52,KILL 52

(2)殺掉會(huì)話(huà),會(huì)引起事務(wù)回滾,同時(shí)釋放排他鎖

四、隔離級(jí)別

4.1 基本概念

「(1)隔離級(jí)別用來(lái)做什么」

  • a.隔離級(jí)別用于決定如何控制并發(fā)用戶(hù)讀寫(xiě)數(shù)據(jù)的操作

「(2)寫(xiě)操作」

  • a.任何對(duì)表做出修改的語(yǔ)句

  • b.使用排他鎖

  • c.不能修改讀操作獲得的鎖和鎖的持續(xù)時(shí)間

「(3)讀操作:」

  • a.任何檢索數(shù)據(jù)的語(yǔ)句

  • b.默認(rèn)使用共享鎖

  • c.使用隔離級(jí)別來(lái)控制讀操作的處理方式

4.2 隔離級(jí)別的分類(lèi)

(1)未提交讀 (READ UNCOMMITTED)

(2)已提交讀(READ COMMITTED)(默認(rèn)值)

(3)可重復(fù)讀(REPEATABLE READ)

(4)可序列化(SERIALIZABLE)

(5)快照(SNAPSHOT)

(6)已經(jīng)提交讀快照(READ_COMMITTED_SNAPSHOT)

4.3 隔離級(jí)別的設(shè)置

「(1)設(shè)置整個(gè)會(huì)話(huà)的隔離級(jí)別」

SET TRANSACTION ISOLATION LEVEL <isolation name>; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

「(2)用表提示設(shè)置查詢(xún)的隔離級(jí)別」

SELECT ... FROM <table> WITH (<isolation name>); SELECT * FROM dbo.myProduct WITH (READCOMMITTED);

注意:

  • 1.設(shè)置會(huì)話(huà)選項(xiàng)的隔離級(jí)別時(shí),隔離級(jí)別中的每個(gè)單詞之間需要用空格分隔

  • 2.用表提示的隔離級(jí)別時(shí),隔離級(jí)別中的每個(gè)單詞之間不需要用空格分隔

  • 3.表提示的隔離級(jí)別有同義詞,如:NOLOCK->READUNCOMMITTED,HOLDLOCK->REPEATABLEREAD

  • 4.隔離級(jí)別的嚴(yán)格性:1.未提交讀<2.已提交讀<3.可重復(fù)讀<4.可序列化

  • 5.隔離級(jí)別越高,一致性越高,并發(fā)性越低

  • 6.基于快照的隔離級(jí)別,SQL Server將提交過(guò)的行保存到tempdb數(shù)據(jù)庫(kù)中,當(dāng)讀操作發(fā)現(xiàn)行的當(dāng)前版本和它們預(yù)期的不一致時(shí),可以立即得到行的以前版本,從而不用請(qǐng)求共享鎖也能取得預(yù)期的一致性。

4.4 隔離級(jí)別的行為方式

4.4.1 未提交讀 (READ UNCOMMITTED)

打開(kāi)兩個(gè)查詢(xún)窗口,Connetion1,connection2

  • Step1: 執(zhí)行Connection1的階段2的SQL 語(yǔ)句,然后執(zhí)行connection2的SQL語(yǔ)句

  • Step2: 執(zhí)行Connection1的階段3的SQL 語(yǔ)句,執(zhí)行connection2的SQL語(yǔ)句

  • Step3: 執(zhí)行Connection1的階段4的SQL 語(yǔ)句,執(zhí)行connection2的SQL語(yǔ)句

--階段2 UPDATE myProduct SET price?=?price?+ 1 WHERE id = 1; SELECT id ,
????????price FROM dbo.myProduct WHERE id = 1; --階段3 UPDATE myProduct SET price?=?price?+ 5 WHERE id = 1; SELECT id ,
????????price FROM dbo.myProduct WHERE id = 1; --階段4 COMMIT TRAN
--在階段2執(zhí)行之后 SET TRAN ISOLATION LEVEL READ UNCOMMITTED BEGIN TRAN; SELECT id ,
????????price FROM dbo.myProduct WHERE id = 1 COMMIT TRAN;

兩個(gè)事務(wù)的流程圖:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 1.未提交讀 READ UNCOMMITTED
  • 階段1:Price=10,事務(wù)A對(duì)myProduct表請(qǐng)求排他鎖

  • 階段2:事務(wù)A對(duì)myProduct表使用了排他鎖,更新price = price + 1,然后事務(wù)A查詢(xún)price的價(jià)格: price=11。事務(wù)B不請(qǐng)求任何鎖,事務(wù)B在A(yíng)更新Price之后進(jìn)行查詢(xún),price=11

  • 階段3:事務(wù)A更新price = price + 5,然后事務(wù)A查詢(xún)price的價(jià)格,price = 16。事務(wù)B查詢(xún)price的價(jià)格: price=16

  • 階段4:事務(wù)A釋放排他鎖

  • 階段5:事務(wù)A中查詢(xún)price的價(jià)格:price = 16。事務(wù)B查詢(xún)price的價(jià)格: price=16

「大家可以看到事務(wù)B有兩種結(jié)果,這就是“未提交讀 (READ UNCOMMITTED)”隔離級(jí)別的含義:」

(1)讀操作可以讀取未提交的修改(也稱(chēng)為臟讀)。

(2)讀操作不會(huì)妨礙寫(xiě)操作請(qǐng)求排他鎖,其他事務(wù)正在進(jìn)行讀操作時(shí),寫(xiě)操作可以同時(shí)對(duì)這些數(shù)據(jù)進(jìn)行修改。

(3)事務(wù)A進(jìn)行了多次修改,事務(wù)B在不同階段進(jìn)行查詢(xún)時(shí)可能會(huì)有不同的結(jié)果。

4.4.2 已提交讀(READ COMMITTED)(默認(rèn)值)

打開(kāi)兩個(gè)查詢(xún)窗口,Connetion1,connection2

Step1: 執(zhí)行Connection1的SQL 語(yǔ)句

UPDATE`?`dbo.myProduct ``SET`?`price?=?price?+ 1 ``WHERE`?`id=1 SELECT`?`* ``FROM`?`dbo.myProduct ``WHERE`?`id =1 

Step2: 執(zhí)行Connection2的SQL 語(yǔ)句

SET`?`TRANSACTION`?`ISOLATION`?`LEVEL`?`READ`?`COMMITTED SELECT`?`* ``FROM`?`dbo.myProduct ``WHERE`?`id = 1 

兩個(gè)事務(wù)的流程圖:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 4.2.2.已提交讀 READ COMMITTED
  • 階段1:Price=10,事務(wù)A對(duì)myProduct表請(qǐng)求排他鎖

  • 階段2:事務(wù)A對(duì)myProduct表使用了排他鎖,更新price = price + 1,然后事務(wù)A查詢(xún)price的價(jià)格: price=11。然后事務(wù)B請(qǐng)求共享鎖進(jìn)行讀操作,查詢(xún)price,

由于在當(dāng)前隔離級(jí)別下,事務(wù)A的排他鎖和事務(wù)B的共享鎖存在沖突,所以事務(wù)B需要等待事務(wù)A釋放排他鎖后才能讀取數(shù)據(jù)。

  • 階段3:事務(wù)A提交事務(wù)(COMMIT TRAN)

  • 階段4:事務(wù)A提交完事務(wù)后,釋放排他鎖

  • 階段5:事務(wù)B獲得了共享鎖,進(jìn)行讀操作,price=11

    「“已提交讀 (READ UNCOMMITTED)”隔離級(jí)別的含義:」

(1)必須獲得共享鎖才能進(jìn)行讀操作,其他事務(wù)如果對(duì)該資源持有排他鎖,則共享鎖必須等待排他鎖釋放。

(2)讀操作不能讀取未提交的修改,讀操作讀取到的數(shù)據(jù)是提交過(guò)的修改。

(3)讀操作不會(huì)在事務(wù)持續(xù)期間內(nèi)保留共享鎖,其他事務(wù)可以在兩個(gè)讀操作之間更改數(shù)據(jù)資源,讀操作因而可能每次得到不同的取值。這種現(xiàn)象稱(chēng)為“不可重復(fù)讀”

4.4.3 可重復(fù)讀(REPEATABLE READ)

打開(kāi)兩個(gè)查詢(xún)窗口,Connetion1,connection2

Step1: 執(zhí)行Connection1的SQL 語(yǔ)句

SET`?`TRANSACTION`?`ISOLATION`?`LEVEL`?`REPEATABLE`?`READ SELECT`?`* ``FROM`?`dbo.myProduct ``WHERE`?`id = 1 

Step2: 執(zhí)行Connection2的SQL 語(yǔ)句

UPDATE`?`dbo.myProduct ``SET`?`price?=?price?+ 1 ``WHERE`?`id=1 

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

兩個(gè)事務(wù)的流程圖:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 4.4.3.可重復(fù)讀 REPEATABLE READ
  • 階段1:Price=10,事務(wù)A對(duì)myProduct表請(qǐng)求共享鎖

  • 階段2:事務(wù)A對(duì)myProduct表使用了共享鎖,事務(wù)A查詢(xún)price的價(jià)格: price=10,事務(wù)A一直持有共享鎖直到事務(wù)A完成為止。然后事務(wù)B請(qǐng)求排他鎖進(jìn)行寫(xiě)操作price=price+1,

由于在當(dāng)前隔離級(jí)別下,事務(wù)A的共享鎖和事務(wù)B請(qǐng)求的排他鎖存在沖突,所以事務(wù)B需要等待事務(wù)A釋放共享鎖后才能修改數(shù)據(jù)。

  • 階段3:事務(wù)A查詢(xún)price, price=10, 說(shuō)明事務(wù)B的更新操作被阻塞了,更新操作沒(méi)有被執(zhí)行。然后事務(wù)A提交事務(wù)(COMMIT TRAN)

  • 階段4:事務(wù)A提交完事務(wù)后,釋放共享鎖

  • 階段5:事務(wù)B獲得了排他鎖,進(jìn)行寫(xiě)操作,price=11

**“可重復(fù)讀 (REPEATABLE READ)”隔離級(jí)別的含義:? **

(1)必須獲得共享鎖才能進(jìn)行讀操作,獲得的共享鎖將一直保持直到事務(wù)完成之止。

(2)在獲得共享鎖的事務(wù)完成之前,沒(méi)有其他事務(wù)能夠獲得排他鎖修改這一數(shù)據(jù)資源,這樣可以保證實(shí)現(xiàn)可重復(fù)的讀取。

(3)兩個(gè)事務(wù)在第一次讀操作之后都將保留它們獲得的共享鎖,所以任何一個(gè)事務(wù)都不能獲得為了更新數(shù)據(jù)而需要的排他鎖,這種情況將會(huì)導(dǎo)致死鎖(deadlock),不過(guò)卻避免了更新沖突。

4.4.4 可序列化(SERIALIZABLE)

打開(kāi)兩個(gè)查詢(xún)窗口,Connetion1,connection2
Step1: 執(zhí)行Connection1的SQL 語(yǔ)句

BEGIN TRANSACTION SET TRANSACTION ISOLATION LEVEL SERIALIZABLE SELECT * FROM dbo.myProduct WHERE id = 1 

Step2: 執(zhí)行Connection2的SQL 語(yǔ)句

INSERT`?`INTO`?`dbo.myProduct(id,?price) ``VALUES`?`(1, 20)

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

兩個(gè)事務(wù)的流程圖:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 4.4.4.可序列化SERIALIZABLE
  • 階段1:Price=10,事務(wù)A對(duì)myProduct表請(qǐng)求共享鎖

  • 階段2:事務(wù)A對(duì)myProduct表使用了共享鎖,事務(wù)A查詢(xún)id=1的price的價(jià)格:1行記錄,price=10,事務(wù)A一直持有共享鎖直到事務(wù)A完成為止。然后事務(wù)B請(qǐng)求排他鎖進(jìn)行插入操作id=1,price=20,

由于在當(dāng)前隔離級(jí)別下,事務(wù)B試圖增加能夠滿(mǎn)足事務(wù)A的讀操作的查詢(xún)搜索條件的新行,所以事務(wù)A的共享鎖和事務(wù)B請(qǐng)求的排他鎖存在沖突,事務(wù)B需要等待事務(wù)A釋放共享鎖后才能插入數(shù)據(jù)。

  • 階段3:事務(wù)A查詢(xún)出id=1的數(shù)據(jù)只有1行,說(shuō)明事務(wù)B的插入操作被阻塞了,插入操作沒(méi)有被執(zhí)行。然后事務(wù)A提交事務(wù)(COMMIT TRAN)

  • 階段4:事務(wù)A提交完事務(wù)后,釋放共享鎖

  • 階段5:事務(wù)B獲得了排他鎖,進(jìn)行插入操作,插入成功,查詢(xún)出id=1的數(shù)據(jù)有兩條-

「“可序列化(SERIALIZABLE)”隔離級(jí)別的含義:」

(1)必須獲得共享鎖才能進(jìn)行讀操作,獲得的共享鎖將一直保持直到事務(wù)完成之止。

(2)在獲得共享鎖的事務(wù)完成之前,沒(méi)有其他事務(wù)能夠獲得排他鎖修改這一數(shù)據(jù)資源,且當(dāng)其他事務(wù)增加能夠滿(mǎn)足當(dāng)前事務(wù)的讀操作的查詢(xún)搜索條件的新行時(shí),其他事務(wù)將會(huì)被阻塞,直到當(dāng)前事務(wù)完成然后釋放共享鎖,其他事務(wù)才能獲得排他鎖進(jìn)行插入操作。

(3)事務(wù)中的讀操作在任何情況下讀取到的數(shù)據(jù)是一致的,不會(huì)出現(xiàn)幻影行(幻讀)。

(4)范圍鎖:讀操作鎖定滿(mǎn)足查詢(xún)搜索條件范圍的鎖。

4.5 隔離級(jí)別總結(jié)

「臟讀:」 讀取未提交的更改。

「不可重復(fù)讀:」 讀操作不會(huì)在事務(wù)持續(xù)期間內(nèi)保留共享鎖,其他事務(wù)可以在兩個(gè)讀操作之間更改數(shù)據(jù)資源,讀操作因而可能每次得到不同的取值。

「丟失更新:」 兩個(gè)事務(wù)進(jìn)行讀操作,獲得資源上的共享鎖,讀取完數(shù)據(jù)后,不再持有資源上的任何鎖,兩個(gè)事務(wù)都能更新這個(gè)值,最后進(jìn)行更新的事務(wù)將會(huì)覆蓋其他事務(wù)做的更改,導(dǎo)致其他事務(wù)更改的數(shù)據(jù)丟失。

「幻讀:」 第一次和第二次讀取到的數(shù)據(jù)行數(shù)不一致。

「范圍鎖:」 讀操作鎖定滿(mǎn)足查詢(xún)搜索條件范圍的鎖

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 隔離級(jí)別總結(jié)

五.死鎖

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 死鎖

死鎖是指一種進(jìn)程之間互相永久阻塞的狀態(tài),可能涉及兩個(gè)或更多的進(jìn)程。

打開(kāi)兩個(gè)查詢(xún)窗口,Connetion1,connection2

Step1: 執(zhí)行Connection1的SQL 語(yǔ)句

SET`?`TRANSACTION`?`ISOLATION`?`LEVEL`?`READ`?`COMMITTED BEGIN`?`TRAN UPDATE`?`dbo.myProduct ``SET`?`price?=?price?+ 1 ``WHERE`?`id=1 SELECT`?`* ``FROM`?`dbo.myOrder ``WHERE`?`id =1 

Step2: 執(zhí)行Connection2的SQL 語(yǔ)句

SET`?`TRANSACTION`?`ISOLATION`?`LEVEL`?`READ`?`COMMITTED BEGIN`?`TRAN UPDATE`?`dbo.myOrder ``SET`?`customer?= ``'ddd'`?`WHERE`?`id = 1 SELECT`?`* ``FROM`?`dbo.myProduct ``WHERE`?`id = 1 

演示與總結(jié)如下所示:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 演示與總結(jié)

兩個(gè)事務(wù)的流程圖:

8000字 | 32 張圖 | 一文搞懂事務(wù)+隔離級(jí)別+阻塞+死鎖 5.死鎖 Dead Lock
  • 階段1:Price=10,事務(wù)A對(duì)myProduct表請(qǐng)求排他鎖。Customer = aaa,事務(wù)B對(duì)myOrder請(qǐng)求排他鎖

  • 階段2:事務(wù)A對(duì)myProduct表使用了排他鎖,更新price = price + 1。然后事務(wù)B對(duì)myOrder表使用了排他鎖,更新customer=ddd。

  • 階段3:事務(wù)A查詢(xún)myOrder表,對(duì)myOrder表請(qǐng)求共享鎖,因?yàn)槭聞?wù)A的請(qǐng)求的共享鎖與事務(wù)B的排他鎖沖突,所以事務(wù)A被阻塞。然后事務(wù)B查詢(xún)myProduct表,對(duì)myProduct表請(qǐng)求共享鎖,因?yàn)槭聞?wù)B的請(qǐng)求的共享鎖與事務(wù)A的排他鎖沖突,所以事務(wù)B被阻塞。

  • 階段4:事務(wù)A等待事務(wù)B的排他鎖釋放,事務(wù)B等待事務(wù)A的排他鎖釋放,導(dǎo)致死鎖。事務(wù)A和事務(wù)B都被阻塞了。

  • 階段5:SQL Server在幾秒之內(nèi)檢測(cè)到死鎖,會(huì)選擇一個(gè)事務(wù)作為死鎖的犧牲品,終止這個(gè)事務(wù),并回滾這個(gè)事務(wù)所做的操作。在這個(gè)例子中,事務(wù)A被終止,提示信息:事務(wù)(進(jìn)程 ID 53)與另一個(gè)進(jìn)程被死鎖在 鎖 資源上,并且已被選作死鎖犧牲品。請(qǐng)重新運(yùn)行該事務(wù)。

「死鎖 (Dead Lock)」” 的一些注意事項(xiàng):

(1)如果兩個(gè)事務(wù)沒(méi)有設(shè)置死鎖優(yōu)先級(jí),且兩個(gè)事務(wù)進(jìn)行的工作量也差不多一樣時(shí),任何一個(gè)事務(wù)都有可能被終止。

(2)解除死鎖要付出一定的系統(tǒng)開(kāi)銷(xiāo),因?yàn)檫@個(gè)過(guò)程會(huì)涉及撤銷(xiāo)已經(jīng)執(zhí)行過(guò)的處理。

(3)事務(wù)處理的時(shí)間時(shí)間越長(zhǎng),持有鎖的時(shí)間就越長(zhǎng),死鎖的可能性也就越大,應(yīng)該盡可能保持事務(wù)簡(jiǎn)短,把邏輯上可以不屬于同一個(gè)工作單元的操作移到事務(wù)以外。

(4)上面的例子中,事務(wù)A和事務(wù)B以相反順序訪(fǎng)問(wèn)資源,所以發(fā)生了死鎖。如果兩個(gè)事務(wù)按同樣的順序來(lái)訪(fǎng)問(wèn)資源,則不會(huì)發(fā)生這種類(lèi)型的死鎖。在不改變程序的邏輯情況下,可以通過(guò)交換順序來(lái)解決死鎖的問(wèn)題。


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀(guān)點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀(guān)點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶(hù)體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(chē)(EV)作為新能源汽車(chē)的重要代表,正逐漸成為全球汽車(chē)產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車(chē)的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車(chē)的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車(chē)場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周?chē)娮釉O(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉