LATCH_EX 等待资源 METADATA_SEQUENCE_GENERATOR

Pau*_*ams 11 sql-server concurrency sql-server-2012 wait-types

我们有一个生成库存报告的流程。在客户端,进程拆分可配置数量的工作线程,为报告构建一个数据块,该数据块对应于许多商店中的一个(可能是数千个,通常是数十个)。每个工作线程调用一个执行存储过程的 Web 服务。

处理每个块的数据库进程将一堆数据收集到一个#Temporary 表中。在每个处理块结束时,数据将写入 tempdb 中的永久表。最后,在进程结束时,客户端的一个线程从永久 tempdb 表中请求所有数据。

运行此报告的用户越多,它的速度就越慢。我分析了数据库中的活动。有一次,我看到 35 个单独的请求在过程中的某一点都被阻止了。所有这些 SPIDLATCH_EX对资源类型的等待时间大约为 50 毫秒METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)。一个 SPID 拥有此资源,而所有其他 SPID 都处于阻塞状态。我在网络搜索中没有找到有关此等待资源的任何信息。

我们正在使用的 tempdb 中的表确实有一IDENTITY(1,1)列。这些 SPID 是否在等待 IDENTITY 列?我们可以使用哪些方法来减少或消除阻塞?

服务器是集群的一部分。服务器在 64 位 Windows 2008 R2 Enterprise 上运行 64 位 SQL Server 2012 Standard Edition SP1。服务器有 64 GB RAM 和 48 个处理器,但数据库只能使用 16 个,因为它是标准版。

(请注意,我对在 tempdb 中使用永久表来保存所有这些数据的设计并不感到兴奋。改变这将是一个有趣的技术和政治挑战,但我愿意接受建议。)

更新 4/23/2013

我们已经与 Microsoft 建立了一个支持案例。随着我们了解更多,我会更新这个问题。

更新 5/10/2013

SQL Server 支持工程师同意等待是由 IDENTITY 列引起的。删除 IDENTITY 消除了等待。我们无法在 SQL 2008 R2 上复制该问题;它仅发生在 SQL 2012 上。

Rac*_*ler 7

(2019 年 2 月更新)

这是一篇旧帖子,它说我终于设法说服微软,这种情况发生的事实确实是一个缺陷。

更新: MS 确认了该缺陷并为其分配了错误编号 12628722。

我在 2018 年 11 月看过这篇文章,当时我们从 Sql Server 2005 升级到 Sql Server 2017 后开始遭受同样的痛苦。 一个 330 万行的表,过去需要 10 秒才能进行批量插入突然开始需要 10带有Identity列的表的分钟数。

事实证明,这背后有两个问题:

  1. Microsoft 更改了 Sql Server 2014 中的行为以强制批量插入并行运行 - 在以前的版本中,批量插入被赋予了序列化计划。
  2. 一旦在我们的 32 核盒子上并行运行,引擎花在内核相互锁定上的时间比实际工作的时间要多。

我花了 4 周时间,但就在假期过后,我收到了圣诞老人送来的迟来的礼物——确认问题确实是一个缺陷。

在解决此问题之前,我们发现了一些可能的解决方法:

  1. Option (MaxDop 1)在查询中使用将批量插入转换回序列化计划。
  2. 通过强制转换来掩盖 Identity 列(例如Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn
    • 这可以防止在使用时复制标识属性 SELECT...INTO
  3. 如上所述删除标识列。
  4. 将数据库兼容模式改为Sql Server 2012或更低版本,重新建立序列化计划。

更新: MS 将实施的修复将是将这些类型的插入返回到使用 Serialized 计划。这是为Sql Server 2017 CU14计划的(没有关于 Sql Server 其他版本的消息 - 抱歉!)。在实施时,跟踪标志9492将需要打开,无论是在服务器级别,或通过 DBCC TraceOn


Jon*_*gel 4

假设您可以将问题隔离到标识值的生成(尝试删除该列作为测试),我建议是这样的:

  1. IDENTITY从最终表的列中删除该属性。
  2. 在每个#Temporary 表中生成标识值。
  3. 加载最终表时,将特定商店的数字标识符与步骤 2 中的标识值结合起来。

因此,如果您的商店 id 为 3 和 4,则最终的 id 值将如下所示:

3000000001
3000000002
3000000003
...
4000000001
4000000002
...
Run Code Online (Sandbox Code Playgroud)

或者类似的东西。你明白了。

这将消除在生成时序列化的需要IDENTITY,同时保留最终结果的唯一性。

或者,根据流程的工作方式,将最终计算的 id 值插入#Temporary 表中。然后,您可以创建一个将它们组合在一起的视图UNION ALL,从而根本不需要复制数据。

  • SQL Server 工程师一致认为这可能是“IDENTITY”列。我们将其从已经很宽的聚集索引中取出,并完全删除了该列。没有必要。之后,这些 LATCH_EX 等待就消失了。我们无法在 SQL 2008 R2 上重复等待。该问题仅发生在 SQL Server 2012 上。 (2认同)