zoukankan      html  css  js  c++  java
  • SQL Server 锁实验(重建索引)

    昨晚某现场报一个重建索引失败的问题,远程查看后发现是自动收缩的内部会话引发的锁申请超时,突然想起来自己的加锁实验还没完成索引重建部分,今天有空正好做一下:

    USE [数据库名]
    GO
    ALTER INDEX <索引名> ON dbo.<表名> REBUILD PARTITION = ALL WITH ( MAXDOP = 4, ONLINE = OFF, SORT_IN_TEMPDB = OFF )
    GO
    

    先试了下聚集索引的重建,以下是相关会话的所有加锁情况:

    从以上的锁分布情况来分析,首先我们过滤掉所有非相关表的锁,那么整个结果集只剩下了6行:

    55	    5	    1589580701	0	    TAB	        S	    GRANT
    55	    5	    1589580701	0	    TAB	        S	    GRANT
    55	    5	    1589580701	0	    TAB	        S	    GRANT
    55	    5	    1589580701	0	    TAB	        S	    GRANT
    55	    5	    1589580701	0	    TAB	        Sch-M   GRANT
    55	    5	    1605580758	0	    TAB	        Sch-M   GRANT
    

    这里出现了4个TAB类型的S锁和一个表级的Sch-M锁以及一个聚集索引的Sch-M锁,从官网提供的锁兼容图来看S锁和Sch-M锁是不兼容的,因此这几个S锁的出现就比较诡异了,查看dm_tran_locks发现request_exec_context_id不一样,而官网对此字段的解释就一句:Execution context ID of the process that currently owns this request.

    所以这里有一个问题:不同的request_exec_context_id代表的TAB类型的S锁到底是什么?为何与Sch-M锁不冲突?

    在SQLOS的任务调度算法中,有一个概念叫做context switch,同计算机原理中的CPU切换一样,意思是同一个CPU针对并发的会话进行线程切换。我们这里只有一个会话一条语句,因此猜测是并行造成的现象。

    事后进行了多次测试,发现开不同的并行数(MAXDOP)目得到的S锁数目与并行数一样,因此这里得request_exec_context_id每个值对应一个并行线程。而针对同一个资源S锁和Sch-M是不兼容的,因此感觉这里的S锁是一个显示小BUG。

    Ps:下图里的object_id与之前的不同是因为不是一个表,无需在意。

    因此重建聚集索引的过程中会对表和涉及的索引加Sch-M的架构锁,而此架构锁与所有其他锁冲突,因此不能再执行任何针对此表的增删改查。

    之后测试了非聚集索引的情况,加锁情况一致因此不作讨论。

  • 相关阅读:
    Redis的常用命令及数据类型
    Redis介绍与安装
    Docker
    Linux Shell——正则表达式
    Linux Shell 基础
    python常见报错
    CMDB
    python学习
    Python 3.x标准模块库目录
    Python笔记——Django路由系统
  • 原文地址:https://www.cnblogs.com/leohahah/p/7201658.html
Copyright © 2011-2022 走看看