在SQL Serve里停用行和頁層級鎖


今天我想談下SQL Server里另一個非常有趣的話題:在SQL Server里停用行和頁層級鎖。在SQL Server里,每次你重建一個索引,你可以使用ALLOW_ROW_LOCKSALLOW_PAGE_LOCKS選項來指定,SQLServer在用讀寫訪問你的數據時,應該獲得行和頁鎖。我們從內部看下,當我們停用這些鎖時會發生什么。

停用行層級鎖

讓我們在一個聚集索引上運行一個簡單的REBUILD操作,這里我們停用行層級鎖:

-- Disable row level locks
ALTER INDEX idx_ci ON Foo REBUILD
WITH (ALLOW_ROW_LOCKS = OFF)
GO

如你從鎖層級里知道的,SQL Server從表層級、頁層級和行級別獲取鎖。現在讓我們在一個顯式事務里運行一個SELECT語句,並且我們用HOLDLOCK查詢提示來把持共享鎖直到事務結束。

-- SQL Server acquires in Repeatable Read a Shared Lock on the Page Level,
-- because Shared Row Locks are not possible anymore.
BEGIN TRANSACTION

SELECT * FROM Foo WITH (HOLDLOCK)
WHERE ID = 5000

SELECT * FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID

ROLLBACK
GO

在這個事務期間,當你查看鎖管理器時,你可以看到SQL Server只在表層級獲得IS所,在頁層級獲得共享鎖,沒有行級別的鎖!

這些獲得的鎖現在沒有約束,因為通常SQL Server在頁層級獲得IS鎖,在行本身獲得共享鎖。當你通過一個事務修改你的數據,這個概念同樣適用。

-- SQL Server acquires for an UPDATE statement an Exclusive Lock on the Page Level,
-- because Exclusive Row Locks are not possible anymore.
BEGIN TRANSACTION

UPDATE Foo
SET Col2 = REPLICATE('y', 100)
WHERE ID = 5000

SELECT * FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID

ROLLBACK
GO

在這個情況下,最后你還是在頁層級有排它鎖,而不是IX鎖。

停用頁層級鎖

接下來讓我們停用頁層級鎖:

-- Disable Page level locks
ALTER INDEX idx_ci ON Foo REBUILD
WITH (ALLOW_PAGE_LOCKS = OFF)
GO

首先我想向你展示下索引重組操作取決於頁層級鎖,因此這個重組操作會失敗:

The index “idx_ci” on table “Foo” cannot be reorganized because page level locking is disabled.

現在讓用重新運行我們的SELECT語句,但這次使用HOLDLOCK查詢提示:

-- There is no IS lock on the Page anymore.
BEGIN TRANSACTION

SELECT * FROM Foo WITH (HOLDLOCK)
WHERE ID = 5000

SELECT * FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID

ROLLBACK
GO

當你再次查看鎖管理器,你會看到在頁層級IS鎖消失了。我們只有在表層級IS鎖,在行層級有共享鎖。

讓我們再來修改一條記錄:

-- There is no IX lock on the Page anymore.
BEGIN TRANSACTION

UPDATE Foo
SET Col2 = REPLICATE('y', 100)
WHERE ID = 5000

SELECT * FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID

ROLLBACK
GO

和剛才一樣的事情發生了:SQL Server在表層級獲得IX鎖,在行上獲得排它鎖。在頁層級沒有鎖……

停用行和葉層級鎖

現在讓我們更進一步,對於我們的具體索引停用行和頁層級鎖:

-- Disable Row and Page level locks
ALTER INDEX idx_ci ON Foo REBUILD
WITH (ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF)
GO

現在當你讀取一些數據,SQL Server只在表層級獲得共享鎖,你的整個表是只讀的:

當你修改沒有獲得頁和行鎖的一條記錄時,SQL Server在整個表上獲得了排它鎖——偶滴神:

小結

這篇文章的意義?為什么你應該在SQL Server里停用頁和行層級鎖,真的沒有一個很好的理由。就用SQL  Server提供的默認的鎖策略即可,因為不然的話鎖會約束太多,從而傷及你的性能……

感謝關注!

原文鏈接:

https://www.sqlpassion.at/archive/2016/10/31/disabling-row-and-page-level-locks-in-sql-server/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM