メモリ最適化 tempdb メタデータ (HkTempDB) のメモリ不足エラー
この記事では、メモリ最適化された tempdb
メタデータ機能に関連するメモリ不足の問題をトラブルシューティングするための解決策について説明します。
現象
メモリ最適化tempdb
メタデータ (HkTempDB) 機能を有効にすると、tempdb
割り当てと SQL Server サービスのクラッシュに関するメモリ不足の例外を示すエラー 701 が表示されることがあります。 さらに、インメモリ OLTP (Hekaton) のメモリ クラーク MEMORYCLERK_XTP
が徐々にまたは急速に成長しており、縮小していないことがわかります。 XTP メモリが上限なしで拡張すると、SQL Server に次のエラー メッセージが表示されます。
リソース プール 'default' のメモリ不足のため、データベース 'tempdb' のページ割り当てを許可しません。 詳細については、「
http://go.microsoft.com/fwlink/?LinkId=510837
」を参照してください。
DMV dm_os_memory_clerks でクエリを実行すると、メモリ クラーク MEMORYCLERK_XTP
に割り当てられたページのメモリが高いことがわかります。 例えば次が挙げられます。
SELECT type, memory_node_id, pages_kb
FROM sys.dm_os_memory_clerks
WHERE type = 'MEMORYCLERK_XTP'
結果:
type memory_node_id pages_kb
------------------------------------------------------------ -------------- --------------------
MEMORYCLERK_XTP 0 60104496
MEMORYCLERK_XTP 64 0
問題を診断する
問題を診断するためにデータを収集するには、次の手順に従います。
軽量トレースまたは拡張イベント (XEvent) を収集してワークロード
tempdb
理解し、ワークロードに一時テーブルの DDL ステートメントを使用して実行時間の長い明示的なトランザクションがあるかどうかを調べる。次の DMV の出力を収集して、さらに分析します。
SELECT * FROM sys.dm_os_memory_clerks SELECT * FROM sys.dm_exec_requests SELECT * FROM sys.dm_exec_sessions -- from tempdb SELECT * FROM tempdb.sys.dm_xtp_system_memory_consumers SELECT * FROM tempdb.sys.dm_db_xtp_memory_consumers SELECT * FROM tempdb.sys.dm_xtp_transaction_stats SELECT * FROM tempdb.sys.dm_xtp_gc_queue_stats SELECT * FROM tempdb.sys.dm_db_xtp_object_stats SELECT * FROM tempdb.sys.dm_db_xtp_transactions SELECT * FROM tempdb.sys.dm_tran_session_transactions SELECT * FROM tempdb.sys.dm_tran_database_transactions SELECT * FROM tempdb.sys.dm_tran_active_transactions
原因と解決策
DMV を使用して原因を確認すると、問題のさまざまなシナリオが表示される場合があります。 これらのシナリオは、次の 2 つのカテゴリに分けることができます。 この問題を解決するには、シナリオごとに対応する解決策を使用できます。 この問題を軽減する方法の詳細については、「 メモリ最適化 tempdb メタデータ メモリをチェック状態に保つためのMitigation 手順を参照してください。
XTP メモリ消費量の段階的な増加
シナリオ 1
DMV tempdb.sys.dm_xtp_system_memory_consumers または tempdb.sys.dm_db_xtp_memory_consumers は、割り当てられたバイトと使用されるバイトの大きな違いを示します。
解決策: この問題を解決するには、 SQL Server 2019 CU13、 SQL Server 2022 CU1、またはそれ以降のバージョンで次のコマンドを実行し、割り当てられているが未使用のバイトを解放する新しいプロシージャ
sys.sp_xtp_force_gc
。Note
SQL Server 2022 CU1 以降ではストアド プロシージャを 1 回だけ実行する必要があります。
/* Yes, 2 times for both*/ EXEC sys.sp_xtp_force_gc 'tempdb' GO EXEC sys.sp_xtp_force_gc 'tempdb' GO EXEC sys.sp_xtp_force_gc GO EXEC sys.sp_xtp_force_gc
シナリオ 2
DMV
tempdb.sys.dm_xtp_system_memory_consumers
は、メモリ コンシューマーの種類のVARHEAP
とLOOKASIDE
に割り当て済みバイトと使用済みバイト数の高い値を示します。解決策: 一時テーブルの DDL ステートメントを含む実行時間の長い明示的なトランザクションを確認し、トランザクションを短くしてアプリケーション側から解決します。
Note
テスト環境でこの問題を再現するには、一時テーブルでデータ定義言語 (DDL) ステートメントを使用して明示的な トランザクション を作成し、他のアクティビティが発生したときに長時間開いたままにすることができます。
シナリオ 3
DMV
tempdb.sys.dm_db_xtp_memory_consumers
は、Object_ID
、XTP_Object_ID
、およびIndex_ID
がNULL
されているラージ オブジェクト (LOB) アロケーターまたはテーブル ヒープの割り当て済みバイトと使用済みバイトの高い値を示します。解決策: 問題14535149SQL Server 2019 CU16 を適用します。
シナリオ 4
"VARHEAP\Storage 内部ヒープ" XTP データベース メモリ コンシューマーが継続的に増加すると、メモリ不足エラー 41805 が発生します。
解決策: 14087445 SQL Server 17 CU25 以降のバージョンで既に特定および解決されている問題は、SQL Server 2019 に移植される予定です。
XTP メモリ消費量の急激な急増または急激な増加
シナリオ 5
DMV
tempdb.sys.dm_db_xtp_memory_consumers
は、Object_ID
がNULL
されていないテーブル ヒープ内の割り当て済みまたは使用済みバイトの高い値を示します。 この問題の最も一般的な原因は、一時テーブル上の DDL ステートメントを使用して実行時間が長く、明示的に開かれているトランザクションです。 例えば次が挙げられます。BEGIN TRAN CREATE TABLE #T(sn int) … … COMMIT
一時テーブルで DDL ステートメントを使用して明示的に開かれたトランザクションでは、
tempdb
メタデータを使用して後続のトランザクションに対してテーブル ヒープとルックアサイド ヒープを解放することはできません。解決策: 一時テーブルの DDL ステートメントを含む実行時間の長い明示的なトランザクションを確認し、トランザクションを短くしてアプリケーション側から解決します。
メモリ最適化 tempdb メタデータ メモリをチェック状態に保つための軽減手順
一時テーブルで DDL ステートメントを使用する実行時間の長いトランザクションを回避または解決するために、一般的なガイダンスはトランザクションを短くすることです。
max サーバー メモリを増やして、tempdb 負荷の高いワークロードが存在する場合に十分なメモリを動作できるようにします。
sys.sp_xtp_force_gc
を定期的に実行します。メモリ不足の可能性からサーバーを保護するには、tempdb を Resource Governor リソース プールにバインドします。 たとえば、
MAX_MEMORY_PERCENT = 30
を使用してリソース プールを作成します。 次に、次の ALTER SERVER CONFIGURATION コマンドを使用して、リソース プールをメモリ最適化 tempdb メタデータにバインドします。ALTER SERVER CONFIGURATION SET MEMORY_OPTIMIZED TEMPDB_METADATA = ON (RESOURCE_POOL = '<PoolName>');
この変更では、メモリ最適化
tempdb
メタデータが既に有効になっている場合でも、再起動を有効にする必要があります。 詳細については、以下を参照してください:警告
HktempDB をプールにバインドした後、プールは最大設定に達する可能性があり、
tempdb
を使用するすべてのクエリがメモリ不足エラーで失敗する可能性があります。 例えば次が挙げられます。リソース プール 'HkTempDB' のメモリ不足のため、データベース 'tempdb' のページ割り当てを禁止しています。 詳細については、「
http://go.microsoft.com/fwlink/?LinkId=510837
」を参照してください。 メモリ不足により XTP がページ割り当てに失敗しました: FAIL_PAGE_ALLOCATION 8特定の状況では、メモリ不足エラーが発生した場合、SQL Server サービスが停止する可能性があります。 この問題が発生する可能性を減らすには、メモリ プールの
MAX_MEMORY_PERCENT
を高い値に設定します。メモリ最適化
tempdb
メタデータ機能では、すべてのワークロードがサポートされるわけではありません。 たとえば、長時間実行される一時テーブルで DDL ステートメントで明示的なトランザクションを使用すると、説明されているシナリオが発生します。 ワークロードにこのようなトランザクションがあり、その期間を制御できない場合は、この機能が環境に適していない可能性があります。HkTempDB
を使用する前に、広範なテストを行う必要があります。
詳細
これらのセクションでは、メモリ最適化 tempdb
メタデータに関連するいくつかのメモリ コンポーネントについて詳しく説明します。
ルックアサイド メモリ アロケーター
インメモリ OLTP のルックアサイドは、高速なトランザクション処理を実現するためのスレッド ローカル メモリ アロケーターです。 各スレッド オブジェクトには、ルックアサイド メモリ アロケーターのコレクションが含まれています。 各スレッドに関連付けられている各ルックアサイドには、割り当て可能なメモリの量に関する事前に定義された上限があります。 制限に達すると、スレッドはスピルオーバー共有メモリ プール (VARHEAP
) からメモリを割り当てます。 DMV sys.dm_xtp_system_memory_consumers
は、各ルックアサイドの種類 (memory_consumer_type_desc = 'LOOKASIDE'
) と共有メモリ プール (memory_consumer_type_desc = 'VARHEAP'
と memory_consumer_desc = 'Lookaside heap'
) のデータを集計します。
システム レベルのコンシューマー: tempdb.sys.dm_xtp_system_memory_consumers
約 25 個のルックアサイド メモリ コンシューマーの種類が上限です。 スレッドがそれらのルックアサイドからより多くのメモリを必要とする場合、メモリはルックアサイド ヒープにスピルオーバーされ、満足されます。 使用されるバイトの値が高い場合は、ワークロードの負荷が一定 tempdb
、または一時オブジェクトを使用する実行時間の長いオープン トランザクションのインジケーターになる可能性があります。
-- system memory consumers @ instance
SELECT memory_consumer_type_desc, memory_consumer_desc, allocated_bytes, used_bytes
FROM sys.dm_xtp_system_memory_consumers
memory_consumer_type_desc memory_consumer_desc allocated_bytes used_bytes
------------------------- ------------------------------------------ -------------------- --------------------
VARHEAP Lookaside heap 0 0
PGPOOL 256K page pool 0 0
PGPOOL 4K page pool 0 0
VARHEAP System heap 458752 448000
LOOKASIDE Transaction list element 0 0
LOOKASIDE Delta tracker cursor 0 0
LOOKASIDE Transaction delta tracker 0 0
LOOKASIDE Creation Statement Id Map Entry 0 0
LOOKASIDE Creation Statement Id Map 0 0
LOOKASIDE Log IO proxy 0 0
LOOKASIDE Log IO completion 0 0
LOOKASIDE Sequence object insert row 0 0
LOOKASIDE Sequence object map entry 0 0
LOOKASIDE Sequence object values map 0 0
LOOKASIDE Redo transaction map entry 0 0
LOOKASIDE Transaction recent rows 0 0
LOOKASIDE Heap cursor 0 0
LOOKASIDE Range cursor 0 0
LOOKASIDE Hash cursor 0 0
LOOKASIDE Transaction dependent ring buffer 0 0
LOOKASIDE Transaction save-point set entry 0 0
LOOKASIDE Transaction FK validation sets 0 0
LOOKASIDE Transaction partially-inserted rows set 0 0
LOOKASIDE Transaction constraint set 0 0
LOOKASIDE Transaction save-point set 0 0
LOOKASIDE Transaction write set 0 0
LOOKASIDE Transaction scan set 0 0
LOOKASIDE Transaction read set 0 0
LOOKASIDE Transaction 0 0
データベース レベルのコンシューマー: tempdb.sys.dm_db_xtp_memory_consumers
LOB アロケーターは、システム テーブルの LOB/行外データに使用されます。
テーブル ヒープは、システム テーブルの行に使用されます。
使用されるバイトの値が高いと、ワークロードの負荷が一定 tempdb
、または一時オブジェクトを使用する実行時間の長いオープン トランザクションのインジケーターになる可能性があります。