【SQL SERVER】鎖機制

来源:https://www.cnblogs.com/WilsonPan/archive/2020/04/02/12618849.html
-Advertisement-
Play Games

SQL Server中鎖機制保證併發情況下的數據訪問,開發過程中利用好索引減少數據,能減少數據掃描數據加鎖的過程,合理規範使用事務,能減少死鎖發生 ...


鎖定是 SQL Server 資料庫引擎用來同步多個用戶同時對同一個數據塊的訪問的一種機制。

  1. 基本概念
  2. 利用SQL Server Profiler觀察鎖
  3. 死鎖產生的原因及避免
  4. 總結

基本概念

資料庫引擎隔離級別

隔離級別定義
未提交的讀取 隔離事務的最低級別,只能保證不讀取物理上損壞的數據。 在此級別上,允許臟讀,因此一個事務可能看見其他事務所做的尚未提交的更改
已提交的讀取 允許事務讀取另一個事務以前讀取(未修改)的數據,而不必等待第一個事務完成。 SQL Server 資料庫引擎保留寫鎖(在所選數據上獲取)直到事務結束,但是一執行 SELECT 操作就釋放讀鎖。 這是SQL Server 資料庫引擎預設級別
可重覆的讀取 SQL Server 資料庫引擎保留在所選數據上獲取的讀鎖和寫鎖,直到事務結束。 但是,因為不管理範圍鎖,可能發生虛擬讀取
可序列化 隔離事務的最高級別,事務之間完全隔離。 SQL Server 資料庫引擎保留在所選數據上獲取的讀鎖和寫鎖,在事務結束時釋放它們。 SELECT 操作使用分範圍的 WHERE 子句時獲取範圍鎖,主要為了避免虛擬讀取
 

鎖粒度

資源說明
RID 用於鎖定堆中的單個行的行標識符,也就是常說的行鎖
KEY 索引中用於保護可序列化事務中的鍵範圍的行鎖
PAGE 資料庫中的 8 KB 頁,例如數據頁或索引頁,也就常說的業級鎖
EXTENT 一組連續的八頁,例如數據頁或索引頁
HoBT 堆或 B 樹。 用於保護沒有聚集索引的表中的 B 樹(索引)或堆數據頁的鎖
TABLE 包括所有數據和索引的整個表
FILE 資料庫文件
APPLICATION 應用程式專用的資源
METADATA 元數據鎖
ALLOCATION_UNIT 分配單元
DATABASE 整個資料庫
 

鎖類型

說明
共用 (S) 用於不更改或不更新數據的讀取操作,如 SELECT 語句
更新 (U) 用於可更新的資源中。 防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖
排他 (X) 用於數據修改操作,例如 INSERT、UPDATE 或 DELETE。 確保不會同時對同一資源進行多重更新
意向 (I) 用於建立鎖的層次結構。 意向鎖包含三種類型:意向共用 (IS)、意向排他 (IX) 和意向排他共用 (SIX)
架構 (Sch-) 在執行依賴於表架構的操作時使用。 架構鎖包含兩種類型:架構修改 (Sch-M) 和架構穩定性 (Sch-S)
大容量更新 (BU) 在將數據大容量複製到表中且指定了 TABLOCK 提示時使用
鍵範圍 (Range) 當使用可序列化事務隔離級別時保護查詢讀取的行的範圍。 確保再次運行查詢時其他事務無法插入符合可序列化事務的查詢的行
 

利用SQL Server Profiler觀察鎖

1. 準備數據10條數據

create table DataTable(Id int identity(1,1), [Name] varchar(50), [Address] varchar(200), CreateTime datetime2)
    
insert into DataTable
select 'Wilson','廣東省廣州市',GETDATE() union all
select 'Alice','北京市朝陽區',GETDATE() union all
select 'Miksovsky','吉林省松原市',GETDATE() union all
select 'Hines','甘肅省蘭州市',GETDATE() union all
select 'Kane','遼寧省沈陽市',GETDATE() union all
select 'Gode','湖北省荊州市',GETDATE() union all
select 'Chen','湖南省岳陽市',GETDATE() union all
select 'Trenary','福建省廈門市',GETDATE() union all
select 'Achong','廣西省玉林市',GETDATE() union all
select 'Nixon','江西省景德鎮',GETDATE() 
View Code

2. 打開SQL Server Profiler選中鎖事件,勾選type和mode,建議取消不需要觀察的列,然後用列篩選器過濾要觀察的DB

3. 查詢數據

 可以看到在頁面級別加上意向共用鎖,因為我們數據只有一頁

4. 更新一條數據

1. 表上加上意向排它鎖(IX),可以用select OBJECT_NAME(581577110) 查看objectid代表的東西

2. 頁級別加上意向更新鎖(IU),告訴SQL Server引擎這裡有更新鎖

3. 獲取第一行的更新鎖(U),這裡條件匹配

4. 頁級別升級為意向排他鎖(IX), 告訴SQL Server引擎這裡有排他鎖

5. 第一個行更新鎖 升級為排它鎖(X)

6. 釋放鎖

7. 隨條掃描後面的記錄,只是條件不符合,也就不會升級鎖級別

 

可以看到是全表掃描,因為沒聚集索引(堆表),我們也沒做一個主鍵,下麵將Id添加主鍵然後再更新試試

alter table DataTable add constraint PK_DataTable primary key(Id asc)

 

 

 可以看出,直接在表,頁級別加上意向排它鎖(IX),然後在鍵上加上排它鎖(X)

因為這裡我們用主鍵更新,而且SQL Server主鍵預設是聚集索引,如果指定是非聚集索引主鍵,這裡也會經歷更新鎖 到 排他鎖,有興趣的可以自行驗證

5. 刪除一條數據

 

 

 這次我們沒用主鍵刪除,過程和更新的第一種情況差不多,就不列了。

因為加了聚集索引,索引定位器執行聚集索引Key的hash,要驗證是否那條記錄,可以在刪除前加上%%lockres%%去查

 

死鎖產生的原因及避免

死鎖產生的原因

微軟文檔是這樣說

在兩個或多個任務中,如果每個任務鎖定了其他任務試圖鎖定的資源,此時會造成這些任務永久阻塞,從而出現死鎖

我理解就是有2個事務迴圈依賴對方的資源導致產生死鎖。

例如

1. 事務A 獲取 Row1 資源

2. 事務B 獲取 Row2 資源

3. 事務A獲取Row2資源,由於這時Row2是被事務B占有,所以必須等事務B完成

4. 事務B獲取Row1資源,由於這時Row1是被事務A占有,所以必須等事務A完成

SQL Server處理死鎖策略

1. 定期檢查陷入死鎖的任務

2. 若檢查到迴圈依賴

3. 選擇其中一個作為犧牲品,然後終止事務,然另外一個得以完成

模擬死鎖

分別在兩個不同的會話執行下麵語句

begin tran;

update DataTable set Address = '上海市' where Id = 2;
--延遲5秒執行
WAITFOR DELAY '00:00:05';
update DataTable set Address = '上海市' where Id = 3;

commit;
begin tran;

update DataTable set Address = '上海市' where Id = 3;
--延遲5秒執行
WAITFOR DELAY '00:00:05';
update DataTable set Address = '上海市' where Id = 2;

commit;

執行一段時間,其中一個會出現下麵錯誤

SQL Server Profiler 捕獲死鎖分析

打開Locks事件的死鎖圖形

 

 重新執行上面語句,模擬死鎖,Profiler捕獲到死鎖

 

可以看出

1. 進程56 請求的Key 的排它鎖  被進程 54 占有

2. 進程54 請求的Key 的排他鎖 被進程 56 占有

3. 形成了迴圈依賴

我們這裡的Sql比較簡單,而且沒有用參數化執行,所以我們指定是哪一行被鎖,線上的通常不能直接看到哪一行被鎖

我們可以通過xml查看等待的資源,在xml裡面有process-list 下麵有多個process,process節點上面有個waitresource屬性,這個指出每個進程等待的資源

鎖類型:db_id : hobt_id : (hashvalue)

KEY: 6:72057594043760640 (61a06abd401c)

通過%%lockres%% 查到被鎖資源

select %%lockres%%,* from DataTable where %%lockres%% = '(98ec012aa510)'

鎖類型不一樣,得到的會不一樣,根據各自的格式用db_name / object_name  / dbcc去查到當前被鎖的資源,有時候需要利用DBCC查詢Page存儲頁面,可以參考上一篇文章【SQL SERVER】數據內部存儲結構簡單探索

避免死鎖

首先需要說明死鎖不能完全避免,但遵守特定的編碼慣例可以將發生死鎖的機會降至最低

1. 按同一順序訪問對象,一個獲取鎖,另外一個就必須等待

2. 避免事務中的用戶交互 ,這樣導致事務時間過長,容易造成死鎖

3. 保持事務簡短並處於一個批處理中,道理和2一樣,儘量讓事務運行時間短。

4. 使用較低的隔離級別,這個看能不能接受臟讀,幻讀等副作用

總結

1. 鎖機制保證併發情況下的數據訪問。

2. 開發中應該儘量利用索引檢索數據,特別是UPDATE/DELETE這種需要排它鎖,應該利用唯一聚集索引欄位更新(通常是主鍵)

3. 規範使用事務能減少死鎖發生

轉發請標明出處:https://www.cnblogs.com/WilsonPan/p/12618849.html

參考文章

事務鎖定和行版本控制指南 - SQL Server | Microsoft Docs


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這篇文章,我們一起來到 Linux 的詭異的一面…… 你知道嗎?在我們日常使用的 Unix(和 Linux )及其各種各樣的分支系統中,存在著一些詭異的命令或進程,它們讓人毛骨悚然,有些確實是有害,但也有些卻是有益的。下麵就來簡單介紹一下這些家伙吧。 1. daemon daemon 有一個很高大上 ...
  • 1、首先安裝好Xshell軟體 2、確認一下Linux系統中是否開啟了sshd服務 sshd服務的命令操作 查看狀態: systemctl status sshd.service 啟動服務: systemctl start sshd.service 重啟服務: systemctl restart s ...
  • 一、 目錄說明 ① Linux的目錄中有且僅有一個根目錄 / ② Linux的各個目錄存放的的內容是規劃好的,不要亂放文件 ③ Linux是以文件的形式管理我們的設備,所以說在Linux系統中,一切皆為文件 要求:Linux中的各個目錄存放什麼內容需要有一個大概的認識。學習完這些目錄後腦海中需要有一 ...
  • cmd運行命令: ver 或者: winver 下表總結了最新的操作系統版本號。 操作系統 | 版本號 | Windows 10 | 10.0 Windows Server 2019| 10.0 Windows Server 2016| 10.0 Windows 8.1| 6.3 Windows S ...
  • 百科 AMD64,或“x64”,是一種64位元的電腦處理器架構。它是基於現有32位元的x86架構,由AMD公司所開發, 應用AMD64指令集的自家產品有Athlon(速龍) 64、Athlon 64 FX、Athlon 64 X2、Turion(炫龍) 64、Opteron(皓龍)、Sempron( ...
  • 簡介 Windows 10 上內置了 Hyper V。Hyper V 提供硬體虛擬化,每個虛擬機都在虛擬硬體上運行。 系統要求 Windows 10 企業版、專業版或教育版。家庭版、移動版、移動企業版無法使用。 具有二級地址轉換 (SLAT) 的 64 位處理器。 CPU 支持 VM 監視器模式擴展 ...
  • 前提:先在centos7中安裝好了VMware Tools 安裝gcc: yum -y install gcc 安裝kernel-devel: yum -y install kernel-devel 設置好共用目錄: 點擊添加之後選擇共用目錄 在centos7終端命令中輸入 vmware-hgfsc ...
  • 最近的項目要求配置共用存儲的四節點集群,使集群能夠形成負載均衡。 但是大家知道,PostgreSQL不支持使用同一數據目錄生成多個實例,在執行pg_ctl start的時候,如果指定的數據目錄有實例在運行,則該實例會發生錯誤導致資料庫down掉。故而,我們選擇了基於pgpool-II + repmg ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...