在SQL Server数据库中,统计信息更新(UPDATE STATISTICS)会被其它会话阻塞吗?统计信息更新(UPDATE STATISTICS)会引起其它会话阻塞吗?在回答这两个问题前,我们必须搞清楚,统计信息更新这个操作期间会申请/持有那些锁。如果弄清楚了这些,那么我们就能很容易回答这两个问题了。如果要弄清楚统计信息更新会申请/持有那些锁,我们可以用SQL脚本或SQL Server Profiler工具来查询/定位相关的锁信息

SQL脚本方式

SELECT * FROM  sys.dm_tran_locks
WHERE request_session_id=xxx;  --xxx用具体的会话ID替换

SELECT resource_type ,
       resource_subtype ,
       resource_description ,
       resource_associated_entity_id ,
       request_mode ,
       request_type ,
       request_status ,
       request_session_id  
FROM sys.dm_tran_locks
WHERE request_session_id = xxx;

用SQL脚本的话,不太容易捕捉到统计信息更新(UPDATE STATISTICS)整个过程中申请的所有相关锁信息,而且小表的统计信息更新速度非常快(时间短到你来不及去查询相关锁信息,有些锁就已经申请成功,并释放了,可能统计信息更新都已经完成了),如果要实验的话,可能需要构造一个很大的表。这种方式还是有一些缺陷与不足。

SQL Server Profiler跟踪方式

使用SQL Server Profiler工具追踪更新统计信息期间会申请/持有哪一些锁。这种方式比较容易捕捉到整个过程中所有相关的锁申请与锁释放的详细信息,而且用SQL Server Profiler跟踪锁的申请与释放也非常方便。个人推荐使用这种方式。

下面我们打开一个会话窗口,找出会话ID(当前测试环境会话ID为53),然后使用SQL Server Profiler跟踪会话ID=53的锁的申请与释放(Lock:Acquired, Lock:Released),此处SQL Server Profiler的相关操作细节略过。然后在会话窗口执行下面语句

UPDATE STATISTICS  TEST WITH FULLSCAN,ALL;

如下部分截图所示,我们可以看到在统计信息更新期间,数据库会在相关对象上请求架构稳定锁(Sch-S)、架构修改锁(Sch-M)、共享锁(S),排它锁(X),意向排他锁(IX),更新锁(U)等,整个过程会有较多的锁申请与锁释放。

从上面实验可以看出,在 SQL Server 中,更新统计信息可能会申请持有很多类型的锁,那么我来一项项分析,在分析之前,我们来看一下锁的兼容矩阵,如果对这方面知识有点模糊不清的,正好可以重温一下这方面的知识点:

注意:除了架构修改锁 (Sch-M)之外,架构稳定锁 (Sch-S) 与所有锁定模式都兼容。而Sch-M 锁与所有锁定模式都不兼容。

1. 共享锁(S)

从实验数据来看,共享锁都发生在统计信息元数据对象上。这些元数据对象,如下截图所示,分别为sysschobjs和sysobjvalues,当然还有OBJECT_ID=0 OBJECTID2=xxxx的数据页或数据行。

SELECT t.object_id AS ObjectID,
       OBJECT_NAME(t.object_id) AS ObjectName,
       SUM(u.total_pages) * 8 AS Total_Reserved_kb,
       SUM(u.used_pages) * 8 AS Used_Space_kb,
       u.type_desc AS TypeDesc,
       MAX(p.rows) AS RowsCount
FROM sys.allocation_units AS u
JOIN sys.partitions AS p ON u.container_id = p.hobt_id
JOIN sys.objects AS t ON p.object_id = t.object_id
where u.allocation_unit_id=281474980642816 
GROUP BY t.object_id,
         OBJECT_NAME(t.object_id),
         u.type_desc
ORDER BY Used_Space_kb DESC,
         ObjectName;

注意:查询条件中用实际具体的OBJECTID2的值替换。

从锁的兼容性来分析的话,这时发生阻塞与被阻塞的可能性是存在的,统计信息更新期间,在申请共享锁时,某些操作在元数据对象上持有意向排他共享锁(SIX)、意向排它锁(IX)、排它锁(X),例如并发的会话跟新统计数据等操作,实际场景中,统计信息更新很少在发生申请共享锁时阻塞其它会话与被其它会话阻塞。

2. 架构稳定性锁(Sch-S)

当UPDATE STATISTICS时,SQL Server 会获取架构稳定锁(Sch-S)。这里不仅仅是统计信息更新涉及的相关对象还包括统计信息元数据对象,都会获取Sch-S锁,而对于架构稳定锁(Sch-S)有下面一些规则:

  • 允许其他会话继续读取或修改数据(如 SELECT、INSERT、UPDATE)。
  • 仅阻塞需要修改表结构的操作(如 ALTER TABLE、CREATE INDEX),因为这些操作需要架构修改锁(Sch-M),与架构稳定锁(Sch-S)不兼容。

此时,除非有并发的会话对表结构进行修改(DDL)或者并发会话在进行统计信息更新操作,此时刚好持有 Sch-M 锁,那么就可能会被阻塞。 我们会结合架构修改锁(Sch-M)构造测试案例。

3. 架构修改锁(Sch-M)

当更新统计信息时,SQL Server 会尝试获取统计信息元数据对象上的架构修改锁(Sch-M)。这种锁用于确保在更新统计信息的过程中,其他会话不会对统计信息进行修改。如果其他会话已经持有与 Sch-M 不兼容的锁(如架构稳定性锁 Sch-S),则更新统计信息的操作可能会被阻塞。

这些元数据对象,如下截图所示,分别为sysschobjs和sysobjvalues等对象。

那么我们简单构造一下统计信息更新被阻塞的案例,如下所示

--会话58中执行下面语句,模拟事务正在修改表结构(DDL),此时事务未提交/事务正在执行阶段

begin tran
alter table test add kk varchar(30);
--rollback;

--会话53中执行下面语句更新统计信息

UPDATE STATISTICS  TEST WITH FULLSCAN,ALL;

在会话窗口监控阻塞情况,如下所示,对表进行DDL操作时,会阻塞统计信息的更新,此时更新统计信息的会话的等待类型为LCK_M_SCH_S,意味着会话53正在等待获取架构稳定锁(Sch-S), 其实反过来,更新统计信息也会阻塞一些会话对相关表进行DDL操作。此时对相关表进行DDL操作时。个人也构造了另外一个大表测试案例进行了验证。有兴趣也可以验证一下。此处略过。

4. 意向排它锁(IX)与排它锁(X)与更新锁(U)

在更新统计信息时,SQL Server 还可能会对相关表(例如,sysobjvalues)中的数据行或页获取行锁(X、U 等)或页锁(IX、IU 等)。这些锁用于确保在采样数据时,数据不会被其他事务修改。如果有并发的DDL或统计信息跟新的话,也有可能导致阻塞与被阻塞。但是实际生产环境中,这种可能性非常小。另外,在表TEST进行统计信息更新时,也会在TEST上有一个短暂的排它锁(X),它的子类型(Resource subtype)为UPDSTATS,根据官方文档[1],只要子类型不同(不同的子类型彼此之间不会冲突),它是不会阻塞表上的DML操作的,除非另外一个会话也在更新统计信息。这种概率微乎其微。

此处附上官方文档的内容:

Represents a subtype of resource_type. Acquiring a subtype lock without holding a non-subtyped lock of the parent type is technically valid. Different subtypes do not conflict with each other or with the non-subtyped parent type. Not all resource types have subtypes.

结论总结

统计信息更新可能被其它会话阻塞,统计信息更新也有可能阻塞其它会话。当统计信息更新时,会获取统计信息元数据对象上的架构修改锁(Sch-M)。如果其他会话已经锁定了同一对象,或者需要在统计信息元数据对象上获取架构稳定性锁(Sch-S)来编译查询的会话,可能会被阻塞。但是这种场景比较少;另外不要同时做DDL(修改表结构、创建维护索引)和统计信息更新操作,不要并发的去做统计信息更新(很少有这种场景)。绝大部分场景下,是可以大胆地执行统计信息更新操作,它不会阻塞数据操作(DML),不用担心它阻塞了其它会话或被阻塞的。

参考资料
[1]

1: https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-locks-transact-sql?view=sql-server-ver16&redirectedfrom=MSDN

SQL Server统计信息更新会被阻塞或引起会话阻塞吗?的更多相关文章

  1. SQL Server 统计信息(Statistics)-概念,原理,应用,维护

    前言:统计信息作为sql server优化器生成执行计划的重要参考,需要数据库开发人员,数据库管理员对其有一定的理解,从而合理高效的应用,管理. 第一部分 概念 统计信息(statistics):描述 ...

  2. 全废话SQL Server统计信息(2)——统计信息基础

    接上文:http://blog.csdn.net/dba_huangzj/article/details/52835958 我想在大地上画满窗子,让所有习惯黑暗的眼睛都习惯光明--顾城<我是一个 ...

  3. 全废话SQL Server统计信息(1)——统计信息简介

    当心空无一物,它便无边无涯.树在.山在.大地在.岁月在.我在.你还要怎样更好的世界?--张晓风<我在> 为什么要写这个内容? 随着工作经历的积累,越来越感觉到,大量的关系型数据库的性能问题 ...

  4. SQL Server统计信息:问题和解决方式

    在网上看到一篇介绍使用统计信息出现的问题已经解决方式,感觉写的很全面. 在自己看的过程中顺便做了翻译. 因为本人英文水平有限,可能中间有一些错误. 假设有哪里有问题欢迎大家批评指正.建议英文好的直接看 ...

  5. SQL Server 统计信息

    SELECT * FROM SYS.stats _WA_Sys_00000009_00000062:统计对象的名称.不同的机器名称不同,自动创建的统计信息都以_WA_Sys开头,00000009表示的 ...

  6. SQL SERVER 统计信息概述(Statistics)

    前言 查询优化器使用统计信息来创建可提高查询性能的查询计划,对于大多数查询,查询优化器已经为高质量查询计划生成必要的统计信息,但是在少数情况下,您需要创建附加的统计信息或者修改查询设计以得到最佳结果. ...

  7. SQL Server 统计信息的创建与更新

    前期准备: 普通表.临时表:它两会有统计信息. 表变量:           不会有统计信息. ---------------------------------------------------- ...

  8. SQL Server 统计信息更新时采样百分比对数据预估准确性的影响

    为什么要写统计信息 最近看到园子里有人写统计信息,楼主也来凑热闹. 话说经常做数据库的,尤其是做开发的或者优化的,统计信息造成的性能问题应该说是司空见惯. 当然解决办法也并非一成不变,“一招鲜吃遍天” ...

  9. SQL Server统计信息偏差影响表联结方式案例浅析

      我们知道数据库中的统计信息的准确性是非常重要的.它会影响执行计划.一直想写一篇关于统计信息影响执行计划的相关博客,但是都卡在如何构造一个合适的例子上,所以一直拖着没有写.巧合,最近在生产环境中遇到 ...

  10. SQL Server 统计信息对查询的影响

    优化器根据开消确定选择哪个执行计划,开消又与行数统计信息有关,默认情况下统计信息是在优化的过程中自动生成的. 一旦列被标记为需要统计信息,查询优化器就会查找该列以有的统计信息,如果以有一个统计信息,下 ...

随机推荐

  1. Java Collections Framework的Fail Fast机制及代码导读

    本文章主要抽取了Java Collections Framework中的Collection接口.List接口.AbstractCollection抽象类.AbstractList抽象类和具体的Arr ...

  2. Spring 开发 Swing GUI 简介

    依赖注入和富客户机 Chad Woolley (thewoolleyman@gmail.com), 软件开发人员, Ionami 简介:  本教程介绍了 Spring 框架以及依赖注入的概念(也称为反 ...

  3. vue之vuex使用

    如图所示,它是一个程序里面的状态管理模式,它是集中式存储所有组件的状态的小仓库,并且保持我们存储的状态以一种可以预测的方式发生变化.对于可以预测,现在我不多做说明,相信在看完这篇文章之后,你就会有自己 ...

  4. vue3-Pinia

    Pinia 是 Vue.js 的一个状态管理库,用于在 Vue 应用程序中管理共享状态.它是 Vuex 的后继者,提供了一个简单.直观且灵活的方式来处理应用中的全局状态,比如用户登录信息.应用配置.购 ...

  5. Java8 Lambda编程常用技巧

    遍历打印List List<Integer> list= Arrays.asList(1,5,6,8,9,32,5,8,7,4,5); list.forEach(System.out::p ...

  6. Vue.js 组件注册

    1.前言 本节讲述组件和2.x版本和3.x版本的注册方式 2.全局注册 2.x版本直接调用Vue.component()方法进行全局注册,所有Vue实例都能使用,包括其组件 //组件代码省略 var ...

  7. VLM-OCR-Demo:一个使用VLM用于OCR任务的示例

    前言 上一篇文章TesseractOCR-GUI:基于WPF/C#构建TesseractOCR简单易用的用户界面中我们构建了一个方便使用TesseractOCR的用户界面,今天构建一个类似的界面,使用 ...

  8. Java Playwright 浏览器最大化

    Playwright 是一个用于自动化 Web 应用测试的现代工具,支持多种语言(包括 Java)及多个浏览器(如 Chromium.Firefox 和 WebKit).它提供了一致的 API 来控制 ...

  9. 《JavaScript 模式》读书笔记(8)— DOM和浏览器模式2

    四.长期运行脚本 可能会注意到有时候浏览器会提示某个脚本已经运行了很长时间,是否应该停止该脚本.实际上无论要处理多么复杂的任务,都不希望应用程序发生上述事情.而且,如果该脚本的工作十分繁重,那么浏览器 ...

  10. 鸿蒙NEXT开发案例:经纬度距离计算

    [引言] 在鸿蒙NEXT平台上,我们可以轻松地开发出一个经纬度距离计算器,帮助用户快速计算两点之间的距离.本文将详细介绍如何在鸿蒙NEXT中实现这一功能,通过简单的用户界面和高效的计算逻辑,为用户提供 ...