今天我想談下SQL Server裏另外一個很是有趣的話題:在SQL Server裏停用行和頁層級鎖。在SQL Server裏,每次你重建一個索引,你可使用ALLOW_ROW_LOCKS 和ALLOW_PAGE_LOCKS選項來指定,SQLServer在用讀寫訪問你的數據時,應該得到行和頁鎖。咱們從內部看下,當咱們停用這些鎖時會發生什麼。html
讓咱們在一個彙集索引上運行一個簡單的REBUILD操做,這裏咱們停用行層級鎖:web
-- Disable row level locks ALTER INDEX idx_ci ON Foo REBUILD WITH (ALLOW_ROW_LOCKS = OFF) GO
如你從鎖層級裏知道的,SQL Server從表層級、頁層級和行級別獲取鎖。如今讓咱們在一個顯式事務裏運行一個SELECT語句,而且咱們用HOLDLOCK查詢提示來把持共享鎖直到事務結束。sql
-- 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所,在頁層級得到共享鎖,沒有行級別的鎖!session
這些得到的鎖如今沒有約束,由於一般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鎖。ui
接下來讓咱們停用頁層級鎖:spa
-- Disable Page level locks ALTER INDEX idx_ci ON Foo REBUILD WITH (ALLOW_PAGE_LOCKS = OFF) GO
首先我想向你展現下索引重組操做取決於頁層級鎖,所以這個重組操做會失敗:code
The index 「idx_ci」 on table 「Foo」 cannot be reorganized because page level locking is disabled.orm
如今讓用從新運行咱們的SELECT語句,但此次使用HOLDLOCK查詢提示:server
-- 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/