SQL Server中SELECT會真的阻塞SELECT嗎?

来源:http://www.cnblogs.com/kerrycode/archive/2017/01/04/6250606.html
-Advertisement-
Play Games

在SQL Server中,我們知道一個SELECT語句執行過程中只會申請一些意向共用鎖(IS) 與共用鎖(S), 例如我使用SQL Profile跟蹤會話86執行SELECT * FROM dbo.TEST WHERE OBJECT_ID =1 這個查詢語句,其申請、釋放的鎖資源的過程如下所示: 而... ...


SQL Server中,我們知道一個SELECT語句執行過程中只會申請一些意向共用鎖(IS) 與共用鎖(S), 例如我使用SQL Profile跟蹤會話86執行SELECT * FROM dbo.TEST WHERE OBJECT_ID =1 這個查詢語句,其申請、釋放的鎖資源的過程如下所示:

 

clipboard

 

而且從最常見的鎖模式的相容性表,我們可以看到IS鎖與S鎖都是相容的,也就是說SELECT查詢是不會阻塞SELECT查詢的。

現有的授權模式

請求的模式

IS

S

U

IX

SIX

X

意向共用 (IS)

共用 (S)

更新 (U)

意向排他 (IX)

意向排他共用 (SIX)

排他 (X)

但是在某些特殊場景。你會看到SELECT語句居然“阻塞”SELECT操作,那麼SQL Server中SELECT會真的阻塞SELECT操作嗎?我們先構造測試的案例場景,那麼先準備測試數據吧

CREATE TABLE TEST (OBJECT_ID  INT, NAME VARCHAR(8));
 
CREATE INDEX PK_TEST ON TEST(OBJECT_ID) 
 
 
DECLARE @Index INT =0;
 
WHILE @Index < 20
BEGIN
    INSERT INTO TEST
    SELECT @Index, 'kerry';
    
    SET @Index = @Index +1;
END

 

在會話視窗A中,執行下麵SQL語句,模擬一個UPDATE語句正在執行

 
BEGIN TRANSACTION
 
    UPDATE dbo.TEST SET NAME='Kerry' WHERE OBJECT_ID=1;
    --ROLLBACK;

 

會話視窗B中,執行下麵的SQL語句

SELECT * FROM dbo.TEST WHERE OBJECT_ID=1

 

會話視窗C中,執行下麵的SQL語句

SELECT * FROM dbo.TEST WHERE OBJECT_ID=1

 

我實驗的場景下,會話視窗A的會話ID為85,會話視窗B的會話ID為90,會話視窗C的會話ID為87,如下所示

clipboard

 

如下所示,你會看到SELECT語句“阻塞”了SELECT語句,即會話90“阻塞”了會話87, 它們的等待事件都為LCK_M_S,也就是說它們都在等待獲取共用鎖,也許你會置疑這個SQL是否有問題,那麼我們使用SP_WHO來查看,你會發現也是如此,如下所示:

clipboard

 

如下所示,我們會發現會話ID為90 、87的會話都在等待類型為RID,Resource為1:24171:1的共用鎖

clipboard

 

其實應該說,會話87、90都在等待RID對象的共用鎖,我們知道共用鎖與意向共用鎖都是相容的,所以SELECT是不會阻塞SELECT的,那麼又怎麼解釋這個現象呢?在宋大神的指點下,粗略的翻了Database System Implementaion這本書(很多原理性知識,看起來相當吃力)。裡面介紹了在鎖表(lock table)以及Element Info、Handling Lock Requests、Handling Unlocks等概念,有一個有意思的圖所示,

clipboard

 

在鎖表(lock table)里,elements info里的鎖的申請是在一個類似隊列的結構。先進先出機制,所以當會話90先進入隊列,它在等待共用鎖(S), 會話87也進入隊列等待共用鎖(S),而且它在會話90的後面(即會話90這個elements info後面的Next指針指向會話87會話的事務),由於兩個會話都被阻塞,這兩個會話的Wait欄位都是Yes,由於內部某些機制,會話87顯示阻塞它的會話為90(這個是我個人臆測,實際具體原因有待考究),實質阻塞的源頭還是會話85. 當會話85釋放排它鎖(X)後,會話隊列根據下麵幾個原則來處理解鎖(Handling Unlocks):

1: First-come-first-served: Grant the lock request that has been waiting the longest. This strategy guarantees no starvation, the situation where a transaction can wait forever for a lock

先來先服務(隊列的原則):授予鎖等待時間最長的鎖請求,這種策略保證不會餓死(翻譯感覺不貼切),即一個事務不會永遠等待鎖的情況。

 

2. Priority to shared locks: First grant all the shared locks waiting. Then,grant one update lock, if there are any waiting. Only grant an exclusive lock if no others are waiting. This strategy can allow starvation, if a transaction is waiting for a U or X lock.

共用鎖優先,首先授予所有等待共用鎖(S),然後授予其中一個更新鎖(U),如果有其它類型等待,只有在沒有其它鎖等待時,才授予排它鎖、這一策略允許等待更新鎖或排它鎖的事務餓死(結束)

 

3. Priority to upgrading: If there is a transaction with a U lock waiting to upgrade it to an X lock, grant that first. Otherwise, follow one of the other strategies mentioned.

鎖升級優先,如果有一個持有共用鎖(U)等待升級Wie排他鎖(X),那麼先授予它排它鎖,否則採用前面已經提到的策略中的一個。

 

按照這些原則,當會話85釋放了排它鎖(X)後,調度器(Scheduler)應該會根據先後順序依次授予會話90、87共用鎖(S),兩者的阻塞會幾乎同時消失。 這個可以也可以通過實驗進行一個大概的推斷, 在上面實驗中,你可以手工取消90會話的查詢操作,然後再查看阻塞情況,就會發現會話87被85阻塞了。這個阻塞的源頭就變成了85,而不是90了。

 

PS:上面是個人結合一些知識和理解,做的一些膚淺的判斷與分析,如果不對的地方,敬請指正!

 

參考資料:

Database System Implementaion


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

-Advertisement-
Play Games
更多相關文章
  • iOS微信第三方登錄實現 一、接入微信第三方登錄準備工作。移動應用微信登錄是基於OAuth2.0協議標準構建的微信OAuth2.0授權登錄系統。在進行微信OAuth2.0授權登錄接入之前,在微信開放平臺註冊開發者帳號,並擁有一個已審核通過的移動應用,並獲得相應的AppID和AppSecret,申請微 ...
  • 由[OpenDigg](http://www.opendigg.com/) 出品的安卓開源項目周報第四期來啦。我們的安卓開源周報集合了OpenDigg一周來新收錄的優質的安卓開發方面的開源項目,方便安卓開發人員便捷的找到自己需要的項目工具等。 ...
  • 崩潰提示:Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <CALayerArray: 0x14df0bd0> was mutated while being enumer ...
  • 參考文章網址: http://www.jianshu.com/p/7a2f49c654df 1.申請APPKey 2.在AppDelegate.m文件中的代碼示例 3.具體的方法實現 ...
  • SignalR 是一個開發實時 Web 應用的 .NET 類庫,使用 SignalR 可以很容易的構建基於 ASP.NET 的實時 Web 應用。SignalR 支持多種伺服器和客戶端,可以 Host 在 7.0 以上的 IIS 伺服器,或者通過 Owin Host 在桌面應用和 Windows 服 ...
  • 以前的Android(4.1之前的版本)中,SDcard路徑通過“/sdcard”或者“/mnt/sdcard”來表示,而在JellyBean(安卓4.1)系統中修改為了" /storage/sdcard0",還會有多個SDcard的情況。目前為了保持和之前代碼的相容,SDcard路徑做了Link映 ...
  • 微信開源,真是喜出望外,必須要去看看啊,比起nuwa來微信好很多,而且github上也有專門的官方文檔說明,還有很多資料查詢 參考地址:https://github.com/Tencent/tinker/wiki https://github.com/Tencent/tinker/wiki/Tink ...
  • 一、安裝 二、登錄用戶管理及密碼修改 b. 選中資料庫,命令:use mysql;c. 查看用戶現有用戶及密碼,註意:mysql5.7用戶密碼欄位為authentication_string,5.7以前為password 三、開啟遠程訪問 四、參考鏈接 MySQL 5.6 for Windows 解 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...