• 在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/

  • 相关阅读:
    mysql(自动添加系统时间)timestamp类型字段的CURRENT_TIMESTAMP与ON UPDATE CURRENT_TIMESTAMP属性
    五分钟带你了解啥是JWT
    Eureka和ZooKeeper的区别
    SpringCloud系列之: Eureka注册中心原理及其搭建
    总结下微服务中降级、熔断,以及springcloud中Hystrix的原理以及实现
    POJ1113:Wall (凸包算法学习)
    Java-Graphics类的绘图方法实现
    java.awt.event.MouseEvent鼠标事件的定义和使用 以及 Java Swing-JTextArea的使用
    java swing JDialog 和 java.util.concurrent的使用
    Java-Swing的JFrame的一些插件使用详解
  • 原文地址:https://www.cnblogs.com/woodytu/p/6044288.html
Copyright © 2020-2023  润新知