SQL2008中SQL應(yīng)用之-鎖定(locking) 應(yīng)用分析

鎖定(Locking)是一個關(guān)系型數(shù)據(jù)庫系統(tǒng)的常規(guī)和必要的一部分,它防止對相同數(shù)據(jù)作 并發(fā)更新 或在更新過程中查看數(shù)據(jù), 從而保證被更新數(shù)據(jù)的完整性。它也能防止用戶讀取正在被修改的數(shù)據(jù) 。

可以鎖定SQL Server中的各種對象,既可以是一個行,也可以是一個表或數(shù)據(jù)庫。可以鎖定的資源在粒度(granularity)上差異很大。從細(xì)(行)到粗(數(shù)據(jù)庫)。細(xì)粒度鎖允許更大的數(shù)據(jù)庫并發(fā),因為用戶能對某些未鎖定的行執(zhí)行查詢。然而,每個由SQL Server產(chǎn)生的鎖都需要內(nèi)存,所以數(shù)以千計獨立的行級別的鎖也會影響SQL Server的性能。粗粒度的鎖降低了并發(fā)性,但消耗的資源也較少。下表介紹SQL Server可以鎖定的資源:

不是所有的鎖都能彼此兼容。例如,一個被排他鎖鎖定的資源不能被再加其他鎖。其他事務(wù)必須等待或超時,直到排他鎖被釋放。被更新鎖鎖定的資源只能接受其他事務(wù)的共享鎖。被共享鎖鎖定的資源還能接受其他的共享鎖或更新鎖。

SQL Server自動分配和升級鎖。升級意味著細(xì)粒度的鎖(行或頁鎖)被轉(zhuǎn)化為粗粒度的表鎖。當(dāng)單個T-SQL語句在單個表或索引上獲取5000多個鎖,或者SQL Server實例中的鎖數(shù)量超過可用內(nèi)存閾值時,SQL Server會嘗試啟動鎖升級。鎖占用系統(tǒng)內(nèi)存,因此把很多鎖轉(zhuǎn)化為一個較大的鎖能釋放內(nèi)存資源。然而,在釋放內(nèi)存資源的同時會降低并發(fā)性。

下面演示一個實例,它使用sys.dm_tran_locks動態(tài)視圖監(jiān)視數(shù)據(jù)庫中鎖的活動。

打開一個查詢窗口,執(zhí)行如下語句:
代碼如下:
USE AdventureWorks
BEGIN TRAN
SELECT ProductID, ModifiedDate
FROM Production.ProductDocument
WITH (TABLOCKX)

打開另一個查詢窗口,執(zhí)行:
代碼如下:
SELECT request_session_id sessionid,
resource_type type,
resource_database_id dbid,
OBJECT_NAME(resource_associated_entity_id, resource_database_id) objectname,
request_mode rmode,
request_status rstatus
FROM sys.dm_tran_locks
WHERE resource_type IN (‘DATABASE’, ‘OBJECT’)

執(zhí)行結(jié)果:
代碼如下:
/*
sessionid type dbid objectname rmode rstatus
51 DATABASE 4 NULL S GRANT
52 DATABASE 4 NULL S GRANT
53 DATABASE 8 NULL S GRANT
56 DATABASE 8 NULL S GRANT
53 OBJECT 8 ProductDocument X GRANT
*/

解析:本示例中,我們首先啟動了一個新事務(wù),并使用TABLOCKX鎖提示(這個提示對表放置了排他鎖),對Production.ProductDocument表執(zhí)行了一個查詢。查詢sys.dm_tran_locks動態(tài)管理視力可以監(jiān)視當(dāng)前SQL Server實例中打開了哪些鎖。它返回了ProductDocument表上的排他鎖。

前三列定義了會話鎖、資源類型和數(shù)據(jù)庫ID。第四列使用了Object_Name函數(shù),注意它使用了兩個參數(shù)(對象ID和數(shù)據(jù)庫ID)來指定訪問哪個名稱(第二個參數(shù)是SQL Server 2005 SP2引入的,它用來指定為了轉(zhuǎn)換對象名稱而使用哪個數(shù)據(jù)庫)。同時也查詢鎖定請求模式和狀態(tài),最后,F(xiàn)rom子句引用DMV,用Where子句指定了兩個資源類型。Resource_Type指定了鎖定的資源類型,如DatabaseObjectFilePageKeyRIDExtentMetadataApplicationAllocation_Unit或HOBT類型。依賴資源類型的resource_associated_entity_id,確定ID是object ID, allocation unit ID, 或Hobt ID。

如果resource_associated_entity_id列包含Object ID(資源類型為Object),可以使用sys.objects目錄視圖來轉(zhuǎn)換名稱。

如果resource_associated_entity_id列包含allocation unit ID(資源類型為Allocation_Unit),可以引用sys.allocatiion_units和contain_id聯(lián)結(jié)到sys.partitions上,就可以確定object ID。

如果resource_associated_entity_id列包含Hobt ID(資源類型為KeypageRow或HOBT),可以直接引用sys.partitions,然后查找相應(yīng)的Object ID。

對于Database、Extent、 Application或MetaData的資源類型,resource_associated_entity_id列將為0。

使用

這是SQL Server 2005中使用的默認(rèn)行為。當(dāng)設(shè)置為該值時,在表級別啟用了鎖升級,不論是否為分區(qū)表。

如果表已分區(qū),則在分區(qū)級別(堆或B樹)啟用鎖升級。如果表未分區(qū),鎖升級將發(fā)生在表級別上。

在表級別刪除鎖升級。注意,對于用了TABLOCK 提示或使用可序列化隔離級別下Heap的查詢時,你仍然可能看到表鎖。

代碼如下:
ALTER TABLE Person.Address
SET (LOCK_ESCALATION = AUTO)
–注意這句在SQL Server 2005下會出錯
SELECT lock_escalation,lock_escalation_desc
FROM sys.tables
WHERE name=’Address’

/*
lock_escalation lock_escalation_desc
2 AUTO
*/

下來,我們禁用鎖升級:
代碼如下:
ALTER TABLE Person.Address
SET ( LOCK_ESCALATION = DISABLE)
SELECT lock_escalation,lock_escalation_desc
FROM sys.tables
WHERE name=’Address’

/*
lock_escalation lock_escalation_desc
1 DISABLE
*/

說明:在更改了這個配置后,可以通過查詢sys.tables目錄視圖的lock_escalation_desc列來驗證這個選項。

注意:如果表未分區(qū),通常情況為表級別升級。如果你指定了Disable選項,將不會出現(xiàn)表級別的鎖升級。這會提高并發(fā)性,但如果你請求訪問大量的行或頁,會增加內(nèi)存的消耗。
邀月 來自 http://www.cnblogs.com/downmoon

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊6 分享