• 可串行化隔离级别里的锁升级


    在今天的文章里我会讨论下可串行化(SERIALIZABLE)隔离级别里会有的锁升级(Lock Escalations),还有你如何避免。在上个月的7月14日,我已经介绍了SQL Server里锁升级(Lock Escalations)的基本概念还有为什么需要它们。因此请你回到这个文章来理解下这个非常重要的概念。

    可串行化(SERIALIZABLE)隔离级别

    可串行化(SERIALIZABLE)隔离级别用来阻止所谓的幻影记录(Phantom Records)。为了阻止它们,SQL Server使用键范围锁定(Key-Range Locking)技术。我们来看下面的SELECT语句: 

    1 SELECT * FROM Person.Address
    2 WHERE StateProvinceID BETWEEN 10 AND 12
    3 GO

    这个语句请求StateProvinceID在10到12之间的所有记录。如果你在可串行化(SERIALIZABLE)隔离级别运行这个语句,这些范围内的IDs会被锁定,保护它不会被数据修改:

    • 你不能INSERT新的记录到保护范围
    • 你不能从保护范围DELETE现有记录
    • 你不能通过UPDATE语句移动现有数据到保护范围

    这个范围之外的修改是允许的,因为SQL Server只锁定了那个特定范围。 

    锁升级(Lock Escalations)

    键范围锁定(Key-Range Locking)技术最重要的是在你的查询谓语上需要支持的非聚集索引。在我们的例子里是StateProvinceID列。如果在它上面没有支持的索引定义,在执行计划里查询优化器会选择聚集索引扫描/表扫描(Clustered Index Scan/Table Scan)运算符。这意味着你必须扫描你的整个表(用残留谓语(residual predicate))来找匹配的记录。

     

    当你在可串行化(SERIALIZABLE)隔离级别里运行你的SELECT语句,在你扫描期间获得超过5000个锁时,你会触发锁升级(Lock Escalations)。下面代码演示了当没有支持的非聚集索引时,你如何触发锁升级(Lock Escalations)。

     1 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
     2 GO
     3 
     4 BEGIN TRANSACTION
     5 
     6 -- The following statement causes a Lock Escalation, because there is no
     7 -- supporting Non-Clustered index on the column "StateProvinceID"
     8 SELECT * FROM Person.Address
     9 WHERE StateProvinceID BETWEEN 10 AND 12
    10 
    11 -- There is only a S lock on the table itself!
    12 SELECT * FROM sys.dm_tran_locks
    13 WHERE request_session_id = @@SPID
    14 
    15 ROLLBACK
    16 GO

    现在让我们创建支持的非聚集索引。

    1 -- Create a supporting Non-Clustered Index
    2 CREATE NONCLUSTERED INDEX idx_StateProvinceID ON Person.Address(StateProvinceID)
    3 GO

    现在当你查看执行计划时,你会看到查询优化器引用了这个新创建的索引并与书签查找(Bookmark Lookup)进行了组合。

    当你在可串行化(SERIALIZABLE)隔离级别里再次运行SELECT语句,你不会触发锁升级了,因为物理上你只读20条请求行。

    小结

    可串行化(SERIALIZABLE)隔离级别是最有限制的一个,它会阻止幻影记录(Phantom Records)。SQL Server内部使用键范围锁定(Key-Range Locking)技术来保持请求范围行的稳定。这里你要记住最重要的是你在你搜索谓语(search predicate)上要有支持的非聚集索引。不然的话你需要扫描你的整个表,如果你读取超过5000行,你就会触发锁升级(Lock Escalations)。

    感谢关注!

    参考文章:

    https://www.sqlpassion.at/archive/2015/01/12/lock-escalations-in-the-isolation-level-serializable/

  • 相关阅读:
    Redis常用数据类型介绍、使用场景及其操作命令
    spring的官方文档地址
    ps基础学习笔记一
    类的加载时机与步骤(转)
    jvm的基本结构以及各部分详解(转)
    jdk1.8使用的url和driverName的改变
    测试框架简单了解
    shiro简单学习的简单总结
    easyui弹框后销毁当前tab弹框不显示的解决方式
    springboot学习章节代码-Spring MVC基础
  • 原文地址:https://www.cnblogs.com/woodytu/p/4695897.html
Copyright © 2020-2023  润新知