2015-02-07 29 views
1

在連接到2014 DB的SQLServer 2014 Management Studio中打開2個窗口。SQL Server鎖定機制刺激

在第一窗口:

SELECT * FROM categorytypes WHERE id = 12 

輸出:

ID DESCRIPTION ORDER 
--------------------- 
12 Electronics 20 

然後:

begin tran 
UPDATE CategoryTypes SET [order] = 20 WHERE id = 12 

現在轉到其它窗口(Ctrl + N鍵):

SELECT * FROM CategoryTypes 

該查詢將無限期執行,直到第一個窗口傳輸提交或回滾。這很好,因爲ID = 12行被鎖定。

SELECT * FROM CategoryTypes WHERE ID <> 12 

工作正常。

SELECT * FROM CategoryTypes WHERE Description = 'MEN' 

這是問題,爲什麼這個查詢應該無限期地執行地獄,我們知道ID = 12的描述「電子」。

在一個大型應用程序中,在同一張表上同時執行巨大的DML過程和選擇操作時,這種鎖定機制不會允許在不同的記錄集上同時執行這兩件事。

在Oracle這種用例的作品中,只要鎖定(髒行)不是結果集的一部分。

夥計們,有沒有什麼辦法可以避免這種Oracle鎖定機制?我不想使用NOLOCK,或將我的交易設置爲READ UNCOMMITTED

謝謝。

+0

你有機會在這裏瞭解鎖。看看sys.dm_tran_locks,看看你的更新事務處理了什麼鎖,以及select所要求的鎖。您可能想要加入sys.dm_tran_session_transactions以將其關聯到session_id。 – 2015-02-07 05:43:17

+0

鎖定在行上不起作用。它適用於索引記錄。根據您的訪問路徑,鎖可能會碰撞或不碰撞。 – usr 2015-02-07 10:12:29

回答

4

在SQL Server中,默認行爲是在默認的READ_COMMITTED隔離級別使用鎖定。通過這種默認鎖定行爲,具有有用的索引特別重要,以便僅觸摸所需的數據。例如,如果您1)在描述中具有索引,並且2)在查詢計劃中使用該索引來查找所需的行,則不會阻止在WHERE子句中使用描述的查詢。如果沒有Description的索引,將導致全表掃描,並且查詢在遇到未提交的更改時將被阻止。

如果您想避免鎖定,使讀者不會阻止編寫者,反之亦然,您可以打開READ_COMMITTED_SNAPSHOT數據庫選項。然後SQL Server將使用行版本控制而不是鎖定來確保只返回提交的數據。

與其他使用行版本控制的DBMS產品一樣,READ_COMMITTED_SNAPSHOT的開銷比內存中的鎖定還要高。 SQL Server每行添加14個字節的額外存儲,並且更多地爲行版本存儲使用tempdb。這些開銷成本是否合理取決於工作負載所帶來的併發優勢。