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

今天我想談下SQL Server裏另外一個很是有趣的話題:在SQL Server裏停用行和頁層級鎖。在SQL Server裏,每次你重建一個索引,你可使用ALLOW_ROW_LOCKSALLOW_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/

相關文章
相關標籤/搜索