Microsoft KB Archive/927396

= Queries take a longer time to finish running when the size of the TokenAndPermUserStore cache grows in SQL Server 2005 =

Article ID: 927396

Article Last Modified on 11/21/2007

-

APPLIES TO


 * Microsoft SQL Server 2005 Developer Edition
 * Microsoft SQL Server 2005 Enterprise Edition
 * Microsoft SQL Server 2005 Enterprise Edition for Itanium-based Systems
 * Microsoft SQL Server 2005 Enterprise X64 Edition
 * Microsoft SQL Server 2005 Standard Edition
 * Microsoft SQL Server 2005 Standard X64 Edition

-



Bug #: 429501 (SQLBUDT)



SYMPTOMS
In Microsoft SQL Server 2005, you may experience the following symptoms:
 * Queries that typically run faster take a longer time to finish running.
 * CPU utilization for the SQL Server process is more than usual.
 * When you experience decreased performance when you run an ad hoc query, you view the query from the sys.dm_exec_requests or sys.dm_os_waiting_tasks dynamic management view. However, the query does not appear to be waiting for any resource.
 * The size of the TokenAndPermUserStore cache store grows at a steady rate.
 * The size of the TokenAndPermUserStore cache store is in the order of several hundred megabytes (MB).
 * In some cases, execution of the DBCC FREEPROCCACHE command provides temporary relief.

To monitor the size of the TokenAndPermUserStore cache, you can use a query that resembles the following: SELECT SUM(single_pages_kb + multi_pages_kb) AS   &quot;CurrentSizeOfTokenCache(kb)&quot; FROM sys.dm_os_memory_clerks WHERE name = 'TokenAndPermUserStore'



CAUSE
The TokenAndPermUserStore cache store maintains the folllowing security token types:
 * LoginToken
 * TokenPerm
 * UserToken
 * SecContextToken
 * TokenAccessResult.

Different classes of TokenAccessResult entries are also present. This specific problem occurs because many TokenAccessResult entries that have a class of 65535 are present.

On an instance of SQL Server that has a high rate of random dynamic query execution, you notice lots of TokenAccessResult entries that have a class of 65535 in the sys.dm_os_memory_cache_entries view. TokenAccessResult entries that have a class of 65535 represent special cache entries. These cache entries are used for cumulative permission checks for queries. For example, you may run the following query: select * from t1 join t2 join t3 In this case, SQL Server computes a cumulative permission check for this query. This check determines whether a user has select on t1, t2, t3. These cumulative permission check results are embedded into a TokenAccessResult entry and are inserted into the TokenAndPermUserStore cache store with an ID of 65535. If the same user reuses or executes this query multiple times, SQL Server reuses the TokenAccessResult cache entry one time.

When this cache store grows, the time to search for existing entries to reuse increases. Access to this cache is controlled so that only one thread can perform the search. This behavior eventually causes query performance to decrease, and more CPU utilization occurs.



Service pack information
To resolve this problem, obtain the latest service pack for SQL Server 2005. For more information, click the following article number to view the article in the Microsoft Knowledge Base:

913089 How to obtain the latest service pack for SQL Server 2005

To resolve this problem, SQL Server 2005 Service Pack 2 changes the caching behavior of the Permission tokens. By default, the TokenAccessResult security cache entry for ad hoc queries is only cached when a specific ad hoc query is executed again.



WORKAROUND
To work around this problem, use one or more of the following methods:  Explicitly parameterize ad hoc queries.

Notes  This method lets you effectively reuse ad hoc queries and their plans. When you use this method, you do not have to create a TokenAccessResult entry every time that you run the ad hoc query together with different parameters. With this method, the size of the TokenAndPermUserStore cache remains under reasonable limits.  Wrap ad hoc queries within stored procedures, and use stored procedures instead of directly executing ad hoc queries.

Notes  Execution plans are cached for the statements that are in the stored procedure.</li> The TokenAccessResult entry for each statement is associated with the execution plan entry.</li> As long as the execution plan for this stored procedure remains in the cache, every execution of the stored procedure effectively reuses the TokenAccessResult entries. Therefore, you do not have to create new TokenAccessResult entries.</li></ul> </li> Enable the FORCE_PARAMETERIZATION database option.

Notes  This method lets you effectively reuse ad hoc queries and their plans.</li> When you use this method, you do not have to create a TokenAccessResult entry every time that you run the ad hoc query together with different parameters.</li> With this method, the size of the TokenAndPermUserStore cache remains under reasonable limits.</li></ul> </li> Add the login that executes varied ad hoc queries as a member of the sysadmin server group.

Notes  TokenAccessResult entries are only created for an ad hoc query when the query is executed by a login that is not a member of the sysadmin server group.</li> Because the TokenAccessResult entries are not created, this behavior keeps the TokenAndPermUserStore cache size to a manageable size.</li></ul> </li> Flush entries from the TokenAndPermUserStore cache.

Notes  <li>To do this, run the following command:

DBCC FREESYSTEMCACHE ('TokenAndPermUserStore')

</li> <li>Ideally, try to watch the threshold of the TokenAndPermUserStore cache size when problems start to appear.</li> <li>You can create a scheduled SQL Server Agent job that performs the following actions: <ul> <li> Check the size of the TokenAndPermUserStore cache size. To do this, run the following command: SELECT SUM(single_pages_kb + multi_pages_kb) AS   &quot;CurrentSizeOfTokenCache(kb)&quot; FROM sys.dm_os_memory_clerks WHERE name = 'TokenAndPermUserStore' </li> <li> If the cache size is bigger than the threshold that you observed, run the following command: DBCC FREESYSTEMCACHE ('TokenAndPermUserStore') </li></ul> </li></ul> </li></ul>

<div class="references_section">