SQL Server で TokenAndPermUserStore キャッシュのサイズが大きくなると、クエリの完了に時間がかかります
この記事は、 TokenAndPermUserStore
のサイズが大きくなるときのクエリ パフォーマンスに関連する問題のトラブルシューティングに役立ちます。 また、さまざまな原因と回避策も提供します。
元の KB 番号: 927396
現象
Microsoft SQL Server では、次の現象が発生します。
通常、高速に実行されるクエリの完了には時間がかかります。
SQL Server プロセスの CPU 使用率が通常より大きい。
アドホック クエリを実行すると、パフォーマンスが低下します。 ただし、
sys.dm_exec_requests
または動的管理ビューsys.dm_os_waiting_tasks
クエリを実行しても、アドホック クエリがリソースを待機していることを示す結果は得られません。TokenAndPermUserStore
キャッシュのサイズは、安定した速度で増加します。TokenAndPermUserStore
キャッシュのサイズは数百メガバイト (MB) です。場合によっては、
DBCC FREEPROCCACHE
またはDBCC FREESYSTEMCACHE
コマンドを実行すると、一時的な解放が提供されます。
原因
高い CPU 使用率やメモリ使用量の増加などのパフォーマンスの問題は、 TokenAndPermUserStore
キャッシュ内の過剰なエントリが原因で発生する可能性があります。 既定では、このキャッシュ内のエントリは、SQL Server が内部メモリ不足を通知した場合にのみクリーンアップされます。 RAM が多いサーバーでは、内部メモリ不足が頻繁にトリガーされないことがあります。 このキャッシュが大きくなると、再利用する既存のエントリを検索するのに時間がかかります。 このキャッシュへのアクセスは、スピンロックによって制御されます。 検索を実行できるのは、一度に 1 つのスレッドだけです。 この動作により、最終的にクエリのパフォーマンスが低下し、CPU 使用率が高くなります。
TokenAndPermUserStore
キャッシュのサイズを監視するには、次のクエリのようなクエリを使用できます。
SELECT SUM(pages_kb) AS
"CurrentSizeOfTokenCache(kb)"
FROM sys.dm_os_memory_clerks
WHERE name = 'TokenAndPermUserStore'
TokenAndPermUserStore
キャッシュでは、次の種類のセキュリティ トークンが保持されます。
- LoginToken
- サーバー レベル プリンシパルごとに 1 つのログイン トークン。
- TokenPerm
- UserToken および SecContextToken のセキュリティ保護可能なオブジェクトのすべてのアクセス許可を記録します。
- このキャッシュ内の各エントリは、特定のセキュリティ保護可能なリソースに対する 1 つのアクセス許可です。 たとえば、ユーザー u1 に対してテーブル t1 に付与された select 権限です。
- このトークン エントリは、アクセス チェック結果 (ACR) キャッシュのエントリとは異なります。 ACR エントリは、主に、ユーザーまたはログインにクエリ全体を実行するアクセス許可があるかどうかを示します。
- UserToken
- ログイン用のデータベースごとに 1 つのユーザー トークン。
- データベース レベルロールのメンバーシップに関する情報を格納します。
- SecContextToken
- サーバー レベル プリンシパルごとに 1 つの SecContextToken が作成されます。
- プリンシパルのサーバー全体のセキュリティ コンテキストを格納します。
- ユーザー トークンのハッシュ テーブル キャッシュが含まれています。
- サーバー レベルのロールのメンバーシップに関する情報を格納します。
- TokenAccessResult
- TokenAccessResult エントリのさまざまなクラスが存在します。
- Access Check は、特定のデータベース内の特定のユーザーが、複数のオブジェクトを含むクエリを実行する権限を持っているかどうかを示します。
- Microsoft SQL Server 2008 より前のバージョンでは、ACR セキュリティ キャッシュは単一のキャッシュ (
TokenAndPermUserStore
) に格納されていました。 - SQL Server 2008 では、ACR キャッシュは分離され、ACR キャッシュ エントリは独自の個々のユーザー ストアで追跡されました。 この分離により、パフォーマンスが向上し、キャッシュのバケット数とクォータ制御が向上しました。
- 現在、使用されているセキュリティ キャッシュの種類は、
TokenAndPermUserStore
とACRCacheStores
だけです。 ACR キャッシュの詳細については、「 access check cache サーバー構成オプションを参照してください。
次のクエリを実行して、さまざまなキャッシュとその個々のサイズに関する情報を取得できます。
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
のクォータを構成するために使用できる 2 つのトレース フラグが用意されています (既定では、クォータはありません。これは、このキャッシュに任意の数のエントリが存在できることを意味します)。
- TF 4618 -
TokenAndPermUserStore
のエントリの数を 1024 に制限します。 - TF 4618+TF 4610 -
TokenAndPermUserStore
のエントリの数を 8192 に制限します。
エントリ数が 4618 と非常に少ない場合は、traceflags 4610 と 4618 を組み合わせて使用します。
トレース フラグ 4610 および 4618 は、オンライン ブックのトピック「 DBCCC TRACEON - トレース フラグに記載されています。
これらのトレース フラグは、 TokenAndPermUserStore
の無制限の増加がサーバーにとって大きすぎるシナリオに使用する必要があります。 これは通常、次の 2 種類の環境で発生します。
TokenAndPermUserStore
がサーバーで使用可能なメモリを大量に占有し、新しいエントリの作成速度がキャッシュの削除率と同じくらい速いロー エンドまたは中規模のハードウェア。 これにより、サーバーの他の部分 (proc キャッシュなど) のメモリ競合やキャッシュの無効化が頻繁に発生する可能性があります。メモリが多いハイエンド コンピューター (たとえば、最近のサポート ケースで 1 TB を超える RAM が必要な場合など)。 これらの環境では、メモリ不足が発生する前にキャッシュ ストアが大きくなる可能性があります。 これにより、長いバケット チェーンまたはウォークによってパフォーマンスが低下する可能性があります。
一時的な軽減策として、次の方法を使用して、このキャッシュを定期的にクリアできます。
TokenAndPermUserStore
キャッシュからエントリをフラッシュします。
注:
そのためには、次のコマンドを実行します。
DBCC FREESYSTEMCACHE ('TokenAndPermUserStore')
問題が発生し始めたときに、
TokenAndPermUserStore
キャッシュ サイズのしきい値を確認します。次のアクションを実行するスケジュールされたSQL Server エージェント ジョブを作成します。
TokenAndPermUserStore
キャッシュのサイズを確認します。 サイズを確認するには、次のコマンドを実行します。SELECT SUM(pages_kb) AS "CurrentSizeOfTokenCache(kb)" FROM sys.dm_os_memory_clerks WHERE name = 'TokenAndPermUserStore'
キャッシュ サイズが観察されたしきい値より大きい場合は、次のコマンドを実行します。
DBCC FREESYSTEMCACHE ('TokenAndPermUserStore')