SQL Server中表鎖定的原理及解鎖演示

有幾個朋友留言建議結合例子來演示一下, 上篇已經說過鎖的幾種類型, 能夠利用系統動態視圖sys.dm_tran_locks查看到,重要的欄位以下:html

 

resource_type 被鎖的資源類型(Database, FILE, Object,PAGE,KEY,EXTENT,RID,APPLICATION,METADATA,HOBT,APPOCATION_UNIT)
request_mode 鎖的類型(共享鎖,更新鎖,排它鎖, 架構鎖等)
resource_description 資源描述
request_session_id Request session ID

 

 

一: 下面以AdventureWorks2008爲示例數據庫作簡要的說明,sql

過濾掉通常的數據庫的共享鎖, 做爲示例必需要看到鎖, 因此用WITH(HOLDLOCK)來保持鎖.數據庫

1. Shared locks (S) 共享鎖session

  1. USE AdventureWorks2008  
  2.  
  3. BEGIN TRAN  
  4. select * from Sales.SalesOrderHeader WITH(HOLDLOCK)  
  5. where SalesOrderID='43662'   
  6.  
  7.       
  8. SELECT resource_type, request_mode, resource_description,
  9. request_session_id, DB_NAME(resource_database_id)as resource_database  
  10. FROM   sys.dm_tran_locks  
  11. WHERE  resource_type <> 'DATABASE' 
  12.  
  13. --ROLLBACK TRAN 

在事務回滾以前, 查看鎖的類型:架構

SQL Server中表鎖定的原理及解鎖演示(圖一)

其餘session對Table只讀, 不能更新, 在開一個新的session測試:併發

  1. select * from Sales.SalesOrderHeader  where SalesOrderID='43662' 
  2.  
  3. go  
  4. update Sales.SalesOrderHeader set OrderDate=GETDATE() where SalesOrderID='43662' 

select能夠正常執行, update語句一直處於等待狀態, 等待上面的session釋放鎖.測試

2. Update locks (U): 更新鎖是共享鎖和獨佔鎖的組合.用UPDLOCK保持更新鎖spa

  1. USE AdventureWorks2008  
  2.  
  3. BEGIN TRAN  
  4. select * from Sales.SalesOrderHeader WITH(UPDLOCK)  
  5. where SalesOrderID='43662'   
  6.       
  7. SELECT resource_type, request_mode, resource_description,
  8. request_session_id,DB_NAME(resource_database_id)as resource_database  
  9. FROM   sys.dm_tran_locks  
  10. WHERE  resource_type <> 'DATABASE' 
  11.  
  12. ROLLBACK TRAN 

查看到鎖的信息:線程

SQL Server中表鎖定的原理及解鎖演示(圖二) 

3.Exclusive locks (X): 獨佔鎖是爲了鎖定數據被一個session修改的數據, 而不可以被另外的session修改. 只能指定NOLOCK來讀取.3d

 

  1. USE AdventureWorks2008  
  2.  
  3. BEGIN TRAN  
  4.  
  5. update Sales.SalesOrderHeader set ShipDate=GETDATE() 
  6. where SalesOrderID='43662' 
  7.       
  8. SELECT resource_type, request_mode, resource_description,
  9. request_session_id,DB_NAME(resource_database_id)as resource_database--,*  
  10. FROM   sys.dm_tran_locks  
  11. WHERE  resource_type <> 'DATABASE' 
  12.  
  13. ROLLBACK TRAN 

查看鎖:

SQL Server中表鎖定的原理及解鎖演示(圖三) 

4.Intent locks (I): 意向鎖用於創建鎖的層次結構. 意向鎖包含三種類型:意向共享 (IS)、意向排他 (IX) 和意向排他共享 (SIX)。

數據庫引擎使用意向鎖來保護共享鎖(S 鎖)或排他鎖(X 鎖)放置在鎖層次結構的底層資源上。 意向鎖之因此命名爲意向鎖,是由於在較低級別鎖前可獲取它們,所以會通知意向將鎖放置在較低級別上。

意向鎖有兩種用途:

防止其餘事務以會使較低級別的鎖無效的方式修改較高級別資源。

提升數據庫引擎在較高的粒度級別檢測鎖衝突的效率。

5. Schema locks (Sch): 架構鎖

Schema stability lock(Sch-S): 保持架構穩定性,用在生成執行計劃時,不會阻止對數據的訪問.

Schema modification lock (Sch-M):用在DDL操做時.當架構正在被改變時, 阻止對對象數據的訪問.

  1. USE AdventureWorks2008  
  2.  
  3. BEGIN TRAN  
  4. CREATE TABLE MyTable (ID INT, NAME VARCHAR(20),COUNTRY VARCHAR(15))  
  5.  
  6. SELECT resource_type, request_mode, resource_description  
  7. FROM   sys.dm_tran_locks  
  8. WHERE  resource_type <> 'DATABASE' order by request_mode  
  9.  
  10. ROLLBACK TRAN 

SQL Server中表鎖定的原理及解鎖演示(圖四)

6. Bulk Update locks (BU)

數據庫引擎在將數據大容量複製到表中時使用了大容量更新 (BU) 鎖, 並指定了 TABLOCK 提示或使用 sp_tableoption 設置了 table lock on bulk load 表選項. 大容量更新鎖(BU 鎖)容許多個線程將數據併發地大容量加載到同一表, 同時防止其餘不進行大容量加載數據的進程訪問該表.

7. Key - Range locks

在使用可序列化事務隔離級別時, 對於 Transact-SQL 語句讀取的記錄集, 鍵範圍鎖能夠隱式保護該記錄集中包含的行範圍. 鍵範圍鎖可防止幻讀. 經過保護行之間鍵的範圍, 它還防止對事務訪問的記錄集進行幻像插入或刪除.

二: 死鎖與死鎖解除

1. 死鎖

使用或管理數據庫都不可避免的涉及到死鎖. 一旦發生死鎖, 數據相互等待對方資源的釋放,會阻止對數據的訪問, 嚴重會形成DB掛掉. 當資源被鎖定, 沒法被訪問時, 能夠終止訪問DB的那個session來達到解鎖的目的(即 Kill掉形成鎖的那個進程).

在兩個或多個任務中,若是每一個任務鎖定了其餘任務試圖鎖定的資源,此時會形成這些任務永久阻塞,從而出現死鎖。 例如:

事務 A 獲取了行 1 的共享鎖。

事務 B 獲取了行 2 的共享鎖。

如今,事務 A 請求行 2 的排他鎖,但在事務 B 完成並釋放其對行 2 持有的共享鎖以前被阻塞。

如今,事務 B 請求行 1 的排他鎖,但在事務 A 完成並釋放其對行 1 持有的共享鎖以前被阻塞。

事務 B 完成以後事務 A 才能完成,可是事務 B 由事務 A 阻塞。該條件也稱爲循環依賴關係: 事務 A 依賴於事務 B,事務 B 經過對事務 A 的依賴關係關閉循環。

除非某個外部進程斷開死鎖,不然死鎖中的兩個事務都將無限期等待下去。 Microsoft SQL Server 數據庫引擎死鎖監視器按期檢查陷入死鎖的任務。 若是監視器檢測到循環依賴關係,將選擇其中一個任務做爲犧牲品,而後終止其事務並提示錯誤。 這樣,其餘任務就能夠完成其事務。 對於事務以錯誤終止的應用程序,它還能夠重試該事務,但一般要等到與它一塊兒陷入死鎖的其餘事務完成後執行。

2. 死鎖檢測

2.1 SQL Server 數據庫引擎自動檢測 SQL Server 中的死鎖循環。數據庫引擎選擇一個會話做爲死鎖犧牲品,而後終止當前事務(出現錯誤)來打斷死鎖。

2.2 查看DMV: sys.dm_tran_locks

2.3 SQL Server Profiler可以直觀的顯示死鎖的圖形事件.

SQL Server中表鎖定的原理及解鎖演示(圖五)

三: 鎖兼容性

鎖兼容性控制多個事務可否同時獲取同一資源上的鎖。 若是資源已被另外一事務鎖定,則僅當請求鎖的模式與現有鎖的模式相兼容時,纔會授予新的鎖請求。 若是請求鎖的模式與現有鎖的模式不兼容,則請求新鎖的事務將等待釋放現有鎖或等待鎖超時間隔過時。 例如,沒有與排他鎖兼容的鎖模式。 若是具備排他鎖(X 鎖),則在釋放排他鎖(X 鎖)以前,其餘事務均沒法獲取該資源的任何類型(共享、更新或排他)的鎖。 另外一種狀況是,若是共享鎖(S 鎖)已應用到資源,則即便第一個事務還沒有完成,其餘事務也能夠獲取該項的共享鎖或更新鎖(U 鎖)。 可是,在釋放共享鎖以前,其餘事務沒法獲取排他鎖。

SQL Server中表鎖定的原理及解鎖演示(圖六)

SQL Server中表鎖定的原理及解鎖演示(圖七)
點擊查看大圖

 

SQL Server中表鎖定的原理及解鎖演示(圖八)

四: 總結

鎖的原理比較抽象,對用戶來講是透明的,不用過多的關注. 應用程序通常不直接請求鎖. 鎖由數據庫引擎的一個部件(稱爲「鎖管理器」)在內部管理. 當數據庫引擎實例處理Transact-SQL 語句時, 數據庫引擎查詢處理器會決定將要訪問哪些資源. 查詢處理器根據訪問類型和事務隔離級別設置來肯定保護每一資源所需的鎖的類型. 而後, 查詢處理器將向鎖管理器請求適當的鎖. 若是與其餘事務所持有的鎖不會發生衝突, 鎖管理器將授予該鎖.

原文:http://www.poluoluo.com/jzxy/201011/98759.html

相關文章
相關標籤/搜索