当 TokenAndPermUserStore 缓存的大小在 SQL Server 中增长时,查询需要更长的时间才能完成

本文可帮助你排查在增长大小 TokenAndPermUserStore 时与查询性能相关的问题。 它还提供了各种原因和解决方法。

原始 KB 数: 927396

现象

在 Microsoft SQL Server 中,会出现以下症状:

  • 通常运行快速的查询需要更长的时间才能完成。

  • SQL Server 进程的 CPU 使用率高于平常。

  • 运行即席查询时,性能会降低。 但是,如果查询 sys.dm_exec_requestssys.dm_os_waiting_tasks 动态管理视图,则结果不会指示即席查询正在等待任何资源。

  • 缓存的大小 TokenAndPermUserStore 以稳定的速度增长。

  • 缓存的大小 TokenAndPermUserStore 为几百兆字节(MB)。

  • 在某些情况下,运行 DBCC FREEPROCCACHEDBCC FREESYSTEMCACHE 命令可提供临时救济。

原因

性能问题(如 CPU 过高和内存使用率增加)可能是缓存中的 TokenAndPermUserStore 条目过多造成的。 默认情况下,仅当 SQL Server 发出内部内存压力时,才会清除此缓存中的条目。 在具有大量 RAM 的服务器上,内部内存压力可能不会经常触发。 当此缓存增长时,搜索现有条目需要更长的时间才能重复使用。 对此缓存的访问由旋转锁控制。 一次只能有一个线程执行搜索。 此行为最终会导致查询性能下降,并且出现更多的 CPU 使用率。

若要监视缓存的大小 TokenAndPermUserStore ,可以使用类似于以下查询的查询:

SELECT SUM(pages_kb) AS 
   "CurrentSizeOfTokenCache(kb)" 
   FROM sys.dm_os_memory_clerks 
   WHERE name = 'TokenAndPermUserStore'

缓存 TokenAndPermUserStore 维护以下安全令牌类型:

  • LoginToken
    • 每个服务器级别主体一个登录令牌。
  • TokenPerm
    • 记录 UserToken 和 SecContextToken 的安全对象的所有权限。
    • 此缓存中的每个条目都是特定安全对象的单个权限。 例如,对表 t1 授予用户 u1 的选择权限。
    • 此令牌条目不同于访问检查结果(ACR)缓存中的条目。 ACR 条目主要指示用户或登录名是否有权运行整个查询。
  • UserToken
    • 每个数据库的一个用户令牌用于登录。
    • 在数据库级别角色中存储有关成员身份的信息。
  • SecContextToken
    • 为每个服务器级别主体创建一个 SecContextToken。
    • 存储主体的服务器范围安全上下文。
    • 包含用户令牌的哈希表缓存。
    • 存储有关服务器级别角色成员身份的信息。
  • TokenAccessResult
    • 存在 TokenAccessResult 条目的不同类。
    • Access Check 指示特定数据库中的给定用户是否有权运行涉及多个对象的查询。
    • Microsoft SQL Server 2008 之前,ACR 安全缓存存储在单个缓存 TokenAndPermUserStore中。
    • 在 SQL Server 2008 中,ACR 缓存被分隔,ACR 缓存条目在各自的单个用户存储中被跟踪。 这种分离提高了性能,为缓存提供了更好的存储桶计数和配额控制。
    • TokenAndPermUserStore目前,也是ACRCacheStores唯一使用的安全缓存类型。 有关 ACR 缓存的详细信息,请参阅 访问检查缓存服务器配置选项

可以运行以下查询来获取有关不同缓存及其各个大小的信息:

SELECT type, name, pages_kb 
FROM sys.dm_os_memory_clerks 
WHERE type = 'USERSTORE_TOKENPERM'

可以运行以下查询来标识在以下项中增长的 TokenAndPermUserStore令牌类型:

SELECT [name] AS "SOS StoreName",[TokenName],[Class],[SubClass], count(*) AS [Num Entries]
FROM
(SELECT name,
x.value('(//@name)[1]', 'varchar (100)') AS [TokenName],
x.value('(//@class)[1]', 'varchar (100)') AS [Class],
x.value('(//@subclass)[1]', 'varchar (100)') AS [SubClass]
FROM
(SELECT CAST (entry_data as xml),name
FROM sys.dm_os_memory_cache_entries
WHERE type = 'USERSTORE_TOKENPERM') 
AS R(x,name)
) a
GROUP BY a.name,a.TokenName,a.Class,a.SubClass
ORDER BY [Num Entries] desc

解决方法

SQL Server 提供了两个可用于配置配额的 TokenAndPermUserStore 跟踪标志(默认情况下,没有配额)。这意味着此缓存中可以有任意数量的条目。

  • TF 4618 - 将条目 TokenAndPermUserStore 数限制为 1024。
  • TF 4618+TF 4610 - 将条目数限制为 TokenAndPermUserStore 8192。

如果 4618 的条目计数非常低会导致其他性能问题,请使用跟踪标志 4610 和 4618。

跟踪标志 4610 和 4618 记录在联机丛书主题 DBCCC TRACEON - 跟踪标志中。

这些跟踪标志应用于未绑定增长 TokenAndPermUserStore 对服务器而言太大的方案。 这通常发生在两种类型的环境中:

  • 低端或中端硬件 TokenAndPermUserStore 占用了服务器的大量可用内存,并且新条目创建速率更快或快于缓存逐出速率。 这可能会导致内存争用和服务器其他部分(例如 proc 缓存)的缓存失效。

  • 具有大量内存的高端计算机(例如,最近的几个支持案例涉及 1 TB 以上的 RAM)。 在这些环境中,缓存存储在遇到任何内存压力之前可能会增大。 这可能会导致长时间的存储桶链或步行性能下降。

作为临时缓解措施,可以使用以下方法定期清除此缓存:

  • TokenAndPermUserStore 缓存刷新条目。

注意:

  1. 为此,请运行以下命令:

    DBCC FREESYSTEMCACHE ('TokenAndPermUserStore')

  2. 出现问题时,请观察缓存大小的阈值 TokenAndPermUserStore

  3. 创建执行以下操作的计划SQL Server 代理作业:

    • 检查缓存的大小 TokenAndPermUserStore 。 若要检查大小,请运行以下命令:

      SELECT SUM(pages_kb) AS 
       "CurrentSizeOfTokenCache(kb)" 
       FROM sys.dm_os_memory_clerks 
       WHERE name = 'TokenAndPermUserStore'
      
    • 如果缓存大小大于观察到的阈值,请运行以下命令:

      DBCC FREESYSTEMCACHE ('TokenAndPermUserStore')