11.5.1 鎖的概念
鎖(Lock) 是在多用戶環境下對資源訪問的一種限制。機制當對一個數據源加鎖後,此數據源就有了一定的訪問限制。我們就稱對此數據源進行了“鎖定”。在SQL Server中,可以對以下的對象進行鎖定:
數據行(Row):數據頁中的單行數據; 索引行(Key):索引頁中的單行數據,即索引的鍵值; 頁(Page):頁是SQL Server 存取數據的基本單位,其大小為8KB; 盤區(Extent):一個盤區由8 個連續的頁組成; 表(Table); 數據庫(Database)。
11.5.2 鎖的類別
在SQL Server 中,鎖有兩種分類方法。
(1) 從數據庫系統的角度來看
鎖分為以下三種類型:
獨占鎖(Exclusive Lock)
獨占鎖鎖定的資源只允許進行鎖定操作的程序使用,其它任何對它的操作均不會被接受。執行數據更新命令,即INSERT、 UPDATE 或DELETE 命令時,SQL Server 會自動使用獨占鎖。但當對象上有其它鎖存在時,無法對其加獨占鎖。獨占鎖一直到事務結束才能被釋放。 共享鎖(Shared Lock)
共享鎖鎖定的資源可以被其它用戶讀取,但其它用戶不能修改它。在SELECT 命令執行時,SQL Server 通常會對對象進行共享鎖鎖定。通常加共享鎖的數據頁被讀取完畢後,共享鎖就會立即被釋放。 更新鎖(Update Lock)
更新鎖是為了防止死鎖而設立的。當SQL Server 准備更新數據時,它首先對數據對象作更新鎖鎖定,這樣數據將不能被修改,但可以讀取。等到SQL Server 確定要進行更新數據操作時,它會自動將更新鎖換為獨占鎖。但當對象上有其它鎖存在時,無法對其作更新鎖鎖定。
(2)從程序員的角度看
鎖分為以下兩種類型:
樂觀鎖(Optimistic Lock)
樂觀鎖假定在處理數據時,不需要在應用程序的代碼中做任何事情就可以直接在記錄上加鎖、即完全依靠數據庫來管理鎖的工作。一般情況下,當執行事務處理時SQL Server會自動對事務處理范圍內更新到的表做鎖定。 悲觀鎖(Pessimistic Lock)
悲觀鎖對數據庫系統的自動管理不感冒,需要程序員直接管理數據或對象上的加鎖處理,並負責獲取、共享和放棄正在使用的數據上的任何鎖。
11.5.3 隔離級別
隔離(Isolation) 是計算機安全學中的一種概念,其本質上是一種封鎖機制。它是指 自動數據處理系統中的用戶和資源的相關牽制關系,也就是用戶和進程彼此分開,且和操 作系統的保護控制也分開來。在SQL Server 中,隔離級(Isolation Level) 是指一個事務 和其它事務的隔離程度,即指定了數據庫如何保護(鎖定)那些當前正在被其它用戶或服 務器請求使用的數據。指定事務的隔離級與在SELECT 語句中使用鎖定選項來控制鎖定 方式具有相同的效果。
在SQL Server 中有以下四種隔離級:
READ COMMITTED
在此隔離級下,SELECT 命令不會返回尚未提交(Committed) 的數據,也不能返回髒數據。它是SQL Server 默認的隔離級。 READ UNCOMMITTED
與READ COMMITTED 隔離級相反,它允許讀取已經被其它用戶修改但尚未提交確定的數據。 REPEATABLE READ
在此隔離級下,用SELECT 命令讀取的數據在整個命令執行過程中不會被更改。此選項會影響系統的效能,非必要情況最好不用此隔離級。 SERIALIZABLE
與DELETE 語句中SERIALIZABLE 選項含義相同。隔離級需要使用SET 命令來設定其語法如下:
SET TRANSACTION ISOLATION LEVEL
{READ COMMITTED
| READ UNCOMMITTED
| REPEATABLE READ
| SERIALIZABLE }
11.5.4 查看鎖
可以通過企業管理器或存儲過程來查看鎖。
(1) 用Enterprise Manager 查看鎖
在企業管理器中選擇目錄樹窗口中“Management” 文件夾下,“Current Activity” 中的“Locks / Process ID” 節點,則可以查看當前鎖定的進程;選擇同級的“Locks / Object”節點下的相應字節點,則可以查看當前鎖定的對象,如圖11-1 所示。在圖11-1 中,右鍵單擊任務板窗口中的對象,從快捷菜單中選擇“屬性”選項,則會出現如圖11-2 所示的鎖的進程細節對話框。在此,可以刷新或殺死鎖的進程。
殺死進程還可以用如下Transact-SQL 命令來進行:
KILL spid
spid 是System Process ID, 即系統進程編號的縮寫,如圖11-1 中所示。
圖11-2 鎖定的進程細節
(2) 用系統存儲過程Sp_lock 查看鎖
存儲過程Sp_lock 的語法如下:
sp_lock spid
SQL Server 的進程編號spid 可以在master.dbo.sysprocesses 系統表中查到。spid 是INT類型的數據,如果不指定spid ,則顯示所有的鎖。
11.5.5 死鎖及其防止
死鎖(Deadlocking) 是在多用戶或多進程狀況下,為使用同一資源而產生的無法解決的爭用狀態,通俗地講,就是兩個用戶各占用一個資源,兩人都想使用對方的資源,但同時又不願放棄自己的資源,就一直等待對方放棄資源,如果不進行外部干涉,就將一直耗下去。
死鎖會造成資源的大量浪費,甚至會使系統崩潰。在SQL Server 中解決死鎖的原則是“犧牲一個比兩個都死強”,即挑出一個進程作為犧牲者,將其事務回滾,並向執行此進程的程序發送編號為1205 的錯誤信息。而防止死鎖的途徑就是不能讓滿足死鎖條件的情況發生,為此,用戶需要遵循以下原則:
盡量避免並發地執行涉及到修改數據的語句; 要求每個事務一次就將所有要使用的數據全部加鎖,否則就不予執行; 預先規定一個封鎖順序所有的事務,都必須按這個順序對數據執行封鎖,例如,不同的過程在事務內部對對象的更新執行順序應盡量保持一致; 每個事務的執行時間不可太長,對程序段長的事務可考慮將其分割為幾個事務。 本章小結
本章中介紹了數據更新的方法及事務和鎖的概念。除了使用本章講述的語句更新數據外,還可以使用視圖來更新數據,有關視圖的運用請參見第13 章“游標和視圖”。