MSSQL死鎖產生原因及解決方法

来源:http://www.cnblogs.com/qiaokai/archive/2016/04/01/5344252.html
-Advertisement-
Play Games

一、 什麼是死鎖 死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去.此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等的進程稱為死鎖進程. 二、 死鎖產生的四個必要條件 互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時 ...


一、    什麼是死鎖

死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去.此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等的進程稱為死鎖進程.

   

二、    死鎖產生的四個必要條件

  • 互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程占用。如果此時還有其它進程請求資源,則請求者只能等待,直至占有資源的進程用畢釋放
  • 請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程占有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放
  • 不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放
  • 環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0,P1,P2,···,Pn}中的P0正在等待一個P1占用的資源;P1正在等待P2占用的資源,……,Pn正在等待已被P0占用的資源

這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。

三、     如何處理死鎖

1)   鎖模式

  1. 共用鎖(S)

由讀操作創建的鎖,防止在讀取數據的過程中,其它事務對數據進行更新;其它事務可以併發讀取數據。共用鎖可以加在表、頁、索引鍵或者數據行上。在SQL SERVER預設隔離級別下數據讀取完畢後就會釋放共用鎖,但可以通過鎖提示或設置更高的事務隔離級別改變共用鎖的釋放時間。

     2.獨占鎖(X)

對資源獨占的鎖,一個進程獨占地鎖定了請求的數據源,那麼別的進程無法在此數據源上獲得任何類型的鎖。獨占鎖一致持有到事務結束。

     3.更新鎖(U)

更新鎖實際上並不是一種獨立的鎖,而是共用鎖與獨占鎖的混合。當SQL SERVER執行數據修改操作卻首先需要搜索表以找到需要修改的資源時,會獲得更新鎖。

更新鎖與共用鎖相容,但只有一個進程可以獲取當前數據源上的更新鎖,

其它進程無法獲取該資源的更新鎖或獨占鎖,更新鎖的作用就好像一個序列化閥門(serialization gate),將後續申請獨占鎖的請求壓入隊列中。持有更新鎖的進程能夠將其轉換成該資源上的獨占鎖。更新鎖不足以用於更新數據—實際的數據修改仍需要用到獨占鎖。對於獨占鎖的序列化訪問可以避免轉換死鎖的發生,更新鎖會保留到事務結束或者當它們轉換成獨占鎖時為止。

      4. 意向鎖(IX,IU,IS)

意向鎖並不是獨立的鎖定模式,而是一種指出哪些資源已經被鎖定的機制。

如果一個表頁上存在獨占鎖,那麼另一個進程就無法獲得該表上的共用表鎖,這種層次關係是用意向鎖來實現的。進程要獲得獨占頁鎖、更新頁鎖或意向獨占頁鎖,首先必須獲得該表上的意向獨占鎖。同理,進程要獲得共用行鎖,必須首先獲得該表的意向共用鎖,以防止別的進程獲得獨占表鎖。

      5. 特殊鎖模式(Sch_s,Sch_m,BU)

SQL SERVER提供3種額外的鎖模式:架構穩定鎖、架構修改鎖、大容量更新鎖。

      6.轉換鎖(SIX,SIU,UIX)

轉換鎖不會由SQL SERVER 直接請求,而是從一種模式轉換到另一種模式所造成的。SQL SERVER 2008支持3種類型的轉換鎖:SIX、SIU、UIX.其中最常見的是SIX鎖,如果事務持有一個資源上的共用鎖(S),然後又需要一個IX鎖,此時就會出現SIX。

      7.鍵範圍鎖

鍵範圍鎖是在可序列化隔離級別中鎖定一定範圍內數據的鎖。保證在查詢數據的鍵範圍內不允許插入數據。

SQL SERVER 鎖模式

縮寫

鎖模式

說明

S

Shared

允許其他進程讀取但不能修改鎖定的資源

X

Exclusive

防止別的進程讀取或者修改鎖定資源中的數據

U

Update

防止其它進程獲取更新鎖或獨占鎖;在搜索要修改的數據時使用

IS

Intent shared

表示該資源的一個組件被共用鎖鎖定了。只有在表或頁級別才能獲得這類鎖

IU

Intent update

表示該資源的一個組件被更新鎖鎖定了。只有在表或頁級別才能獲得這類鎖

IX

Intent exclusive

表示該資源的一個組件被獨占鎖鎖定了。只有在表或頁級別才能獲得這類鎖

SIX

Shared with intent exclusive

表示一個正持有共用鎖的資源還有一個組件(一頁或一行)被獨占鎖鎖定了

SIU

Shared with intent   Update

表示一個正持有共用鎖的資源還有一個組件(一頁或一行)被更新鎖鎖定了

UIX

Update with intent exclusive

表示一個正持有更新鎖的資源還有一個組件(一頁或一行)被獨占鎖鎖定了

Sch-S

Schema stability

表示一個使用該表的查詢正在被編譯

Sch-M

Schema modification

表示表的結構正在被修改

BU

Bulk Update

在一個大容量複製操作將數據導入表中並且(手動或自動)應用了TABLOCK查

詢提示時使用

 

2)   鎖粒度

SQL SERVER 可以在表、頁、行等級別鎖定用戶的數據資源即非系統資源(系統資源是用閂鎖來保護的)。此外SQL SERVER 還可以鎖定索引鍵和索引鍵範圍。

通過sys.dm_tran_locks視圖可以查看誰被鎖定了(如行,鍵,頁)、鎖的模式以及特定資源的標誌符。基於sys.dm_tran_locks視圖創建如下視圖用於查看鎖定的資源以及鎖模式(通過這個視圖可以查看事務鎖定的表、頁、行以及加在數據資源上的鎖類型)。

CREATE VIEW dblocks AS  
SELECT request_session_id AS spid, 
       DB_NAME(resource_database_id) AS dbname, 
       CASE WHEN resource_type='object'  
                 THEN OBJECT_NAME(resource_associated_entity_id)  
            WHEN resource_associated_entity_id=0 THEN 'n/a' 
            ELSE OBJECT_NAME(p.object_id) END AS entity_name, 
       index_id, 
       resource_type AS RESOURCE, 
       resource_description AS DESCRIPTION, 
       request_mode AS mode, 
       request_status AS STATUS  
FROM sys.dm_tran_locks t LEFT JOIN sys.partitions p ON p.partition_id=t.resource_associated_entity_id 
WHERE resource_database_id=DB_ID()

 

3)   如何跟蹤死鎖

通過選擇sql server profiler 事件中的如下選項就可以跟蹤到死鎖產生的相關語句。

 

4)   死鎖案例分析

 

在該案例中process65db88, process1d0045948為語句1的進程,process629dc8 為語句2的進程; 語句2獲取了1689766頁上的更新鎖,在等待1686247頁上的更新鎖;而語句1則獲取了1686247頁上的更新鎖在等待1689766頁上的更新鎖,兩個語句等待的資源形成了一個環路,造成死鎖。

5)   如何解決死鎖

針對如上死鎖案例,分析其對應語句執行計劃如下:

 

          通過執行計劃可以看出,在查找需要更新的數據時使用的是索引掃描,比較耗費性能,這樣就造成鎖定資源時間過長,增加了語句併發執行時產生死鎖的概率。

 處理方式:

1. 在表上建立一個聚集索引。

2. 對語句更新的相關欄位建立包含索引。

優化後該語句執行計劃如下:

          

            優化後的執行計劃使用了索引查找,將大幅提升該查詢語句的性能,降低了鎖定資源的時間,同時也減少了鎖定資源的範圍,這樣就降低了鎖資源迴圈等待事件發生的概率,對於預防死鎖的發生會有一定的作用。

            死鎖是無法完全避免的,但如果應用程式適當處理死鎖,對涉及的任何用戶及系統其餘部分的影響可降至最低(適當處理是指發生錯誤1205時,應用程式重新提交批處理,第二次嘗試大多能成功。一個進程被殺死,它的事務被取消,它的鎖被釋放,死鎖中涉及到的另一個進程就可以完成它的工作並釋放鎖,所以就不具備產生另一個死鎖的條件了。)

 

四、     如何預防死鎖

    阻止死鎖的途徑就是避免滿足死鎖條件的情況發生,為此我們在開發的過程中需要遵循如下原則:

  1. 儘量避免併發的執行涉及到修改數據的語句。
  2. 要求每一個事務一次就將所有要使用到的數據全部加鎖,否則就不允許執行。
  3. 預先規定一個加鎖順序,所有的事務都必須按照這個順序對數據執行封鎖。如不同的過程在事務內部對對象的更新執行順序應儘量保證一致。
  4. 每個事務的執行時間不可太長,對程式段的事務可考慮將其分割為幾個事務。在事務中不要求輸入,應該在事務之前得到輸入,然後快速執行事務。
  5. 使用儘可能低的隔離級別。
  6. 數據存儲空間離散法。該方法是指採用各種手段,將邏輯上在一個表中的數據分散的若幹離散的空間上去,以便改善對錶的訪問性能。主要通過將大表按行或者列分解為若幹小表,或者按照不同的用戶群兩種方法實現。
  7. 編寫應用程式,讓進程持有鎖的時間儘可能短,這樣其它進程就不必花太長的時間等待鎖被釋放。

 


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

-Advertisement-
Play Games
更多相關文章
  • 9. 存儲 9. 存儲... 1 9.1 存儲引擎... 1 9.1.1 WiredTiger存儲引擎... 1 9.1.1.1 文檔級別併發... 1 9.1.1.2 快照和檢查點... 2 9.1.1.3 Journaling. 2 9.1.1.4 壓縮... 2 9.1.1.5 記憶體使用... ...
  • 如下: 輸出如下: 這個腳本主要利用了mysqladmin提供的功能 ext是extended-status的縮寫~ ...
  • mysql 格式語句規範如何登陸你的資料庫?舉例! 如果你的是 編譯安裝的花 那就得去編譯安裝後的那個目錄中去,我的是安裝到/usr/local/mysql 下登陸資料庫:cd /usr/local/mysqlbin/mysql -u root -p然後輸入密碼mysql-> show databa ...
  • 索引查詢是資料庫中重要的記錄查詢方法,要不要進入索引以及在那些欄位上建立索引都要和實際資料庫系統的查詢要求結合來考慮,下麵給出實際中的一些通用的原則: 1. 在經常用作過濾器的欄位上建立索引; 2. 在SQL語句中經常進行GROUP BY、ORDER BY的欄位上建立索引; 3. 在不同值較少的欄位 ...
  • 我們知道從MySQL表中使用SQL SELECT 語句來讀取數據。 如需有條件地從表中選取數據,可將 WHERE 子句添加到 SELECT 語句中。 語法 以下是SQL SELECT 語句使用 WHERE 子句從數據表中讀取數據的通用語法: 查詢語句中你可以使用一個或者多個表,表之間使用逗號(,)分 ...
  • 使用 mysqladmin 創建資料庫 使用普通用戶,你可能需要特定的許可權來創建或者刪除 MySQL 資料庫。 所以我們這邊使用root用戶登錄,root用戶擁有最高許可權,可以使用 mysql mysqladmin 命令來創建資料庫。 實例 以下命令簡單的演示了創建資料庫的過程,數據名為 TUTOR ...
  • 常用MySql命令列選 命令 參數 含義 alter 資料庫,表 修改資料庫或表 backup 表 備份表 \c 取消輸入 create 資料庫,表 創建資料庫或表 delete 表和行的表達式 從表中刪除行 describe 表 說明表的列 drop 資料庫,表 刪除資料庫或表 exit(ctrl ...
  • 1. Question Description: 1.1 mysql version: mysql-5.7.11-win64.zip 1.2 if you connect to the mysql service the first time, you may come across some pr ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...