web-dev-qa-db-ja.com

SQL Serverに使用可能な物理メモリが残っていない場合はどうなりますか?

グーグルで調べていると、矛盾する情報が見つかりました。

一部のサイトでは、データ用の物理メモリが残っていない場合、SQL Serverは既存のデータをTEMPDBに移動します( SQL Server:Demystifying TempDb and recommendations )。

しかし、他のサイトでは、十分な物理メモリが残っていない場合、オペレーティングシステムはページファイルを使用してデータを物理メモリからそこに移動できると述べています( SQL Serverのページファイル を参照)。 )。

SQL Serverが物理メモリを使い果たしたときに、SQL Serverがどこにデータを書き込むのでしょうか。 tempdbまたはOSページファイルに?それとも両方?

16
RaufDBA

データ用の物理メモリが残っていない場合、SQL Serverは既存のデータをTEMPDBに移動します

あなたがリンクした記事はせいぜい誤解を招くものであり、場所によっては正しくありません。著者はいくつかの複雑なことを過度に単純化しようと試みていたと思いますが、そうすることで少し行き過ぎました。

SQL Serverは、メモリ(バッファープール)からtempdbにデータを移動しません。 (最近使用した)キャッシュ戦略(一般的に)を使用しているため、メモリの負荷があり、新しいデータをメモリにプルする必要がある場合、SQL Serverは新しいデータに対応するためにバッファプールからLRUデータを取り出します。この動作は、多くの場合、 "Page Life Expectancy"(PLE) と呼ばれるperfmonカウンターによって監視されます。

PLEの定義は、バッファープールに読み込まれたデータファイルページ(データファイルページのインメモリキャッシュ)がメモリに残り、別のデータ用のスペースを確保する前にメモリに留まる予想時間(秒単位)です。ファイルページ。 PLEを考えるもう1つの方法は、ディスクから読み取られるページ用の空き領域を作成するためのバッファープールへの圧力を瞬時に測定することです。これらの定義の両方で、数値が大きいほど優れています。

クエリの実行中、SQL Serverは特定の操作にtempdbを使用できます。これは通常、見積もりが悪い場合に行われますが、使用可能なメモリが少ないと、この動作に影響を与える可能性があります。

この方法でtempdbに "流出"する可能性のある操作には、行のハッシュ(結合や集計など)、メモリ内の行の並べ替え、並列クエリ実行中の行のバッファリングなどがあります。

ユーザークエリでは、tempdb(グローバルまたはローカルの一時テーブルを使用)を明示的に使用したり、tempdb(スナップショットまたはコミットされたスナップショット分離レベルを読み取り)を暗黙的に使用したりすることもできます。

これらの状況はどちらも、あなたが引用した声明に実際には適合しないようです。

十分な物理メモリが残っていない場合、オペレーティングシステムはページファイルを使用して、物理メモリからそこにデータを移動できます。

これは間違いなく発生する可能性があり、ほとんどの場合SQL Serverの制御の範囲外です。一部のタイプのOSレベルのページングを防止するために回すことができるノブがあります。つまり、 "Lock Pages in Memory"(LPIM) をオンにします。

このWindowsポリシーは、どのアカウントがプロセスを使用してデータを物理メモリに保持できるかを決定し、システムがディスク上の仮想メモリにデータをページングできないようにします。

では、ディスクにページングされないようにするにはどうすればよいでしょうか。

SQL Server 2012より前のバージョンでは、「シングルページアロケーター」と呼ばれるコンポーネントを介して割り当てられたページがメモリにロックされていました(ページングできませんでした)。これには、バッファープール(データベースページ)、プロシージャキャッシュ、およびその他のメモリ領域が含まれます。

詳細については、 ロックされたページ、AWE、タスクマネージャー、およびワーキングセットでの楽しみ… 、特に「4. x64上のSQL Serverが "ロックされたページ"を使用できることを知っています。ロックされている?」その他の関連する読み物はここにあります: 偉大なSQL Serverの論争:メモリ内のページのロック

SQL Server 2012以降では、「シングルページアロケーター」はありません(シングルおよびマルチページアロケーターがマージされました メモリの詳細な考察– SQL Server 2012/2014 )。ページングできるものとできないものの詳細については、私が見たどこにも詳しく文書化されていません。クエリ (like this )を使用して、isがロックされているかを確認できます。

select osn.node_id, osn.memory_node_id, osn.node_state_desc, omn.locked_page_allocations_kb
from sys.dm_os_memory_nodes omn
inner join sys.dm_os_nodes osn on (omn.memory_node_id = osn.memory_node_id)
where osn.node_state_desc <> 'ONLINE DAC'

同じMSサポート記事に従って、DBCC MEMORYSTATUS「ロックされている」メモリの量を確認します。

補足として、SQL ServerのワーキングセットがOSによってページングされている証拠をエラーログで確認できます。次のようなメッセージが表示されます。

2019-09-02 10:19:27.29 spid11s SQLサーバープロセスメモリのかなりの部分がページアウトされました。これにより、パフォーマンスが低下する可能性があります。時間:329秒。ワーキングセット(KB):68780、コミット済み(KB):244052、メモリ使用率:28%。

28
Josh Darnell

SQLサーバーの最新バージョンでは、完全にハングアップする可能性が非常に低くなっています。 SQL Serverは.NET Frameworkをアドレス空間にロードし、通常の操作で使用します。物理メモリとページファイルの両方が不足すると、Windowsはページファイルを拡張しようとします。ただし、ページファイルを拡張できる場合でも、これは瞬時の操作ではなく、ページファイルの拡張中にメモリ割り当ては失敗します。 .NET非同期I/Oハンドラーにバグがあり、APC通知に応答してメモリを割り当てます。 newの呼び出しが失敗すると、OutOfMemoryExceptionがスローされます。この例外は、タスクスケジューラ内のネイティブコードでキャッチされます。ただし、非同期I/Oは終了しないように見えます。 FileStreamのファイナライザスレッドは、I/Oが完了するのを待ってブロックするため、バッファの固定を解除できるため、ファイナライザスレッドが永久にハングアップします。これにより、.NET Frameworkは、メモリを割り当てることができなくなるまで徐々にメモリを使用し続けます。その時点で、winsockはこれ以上バッファを割り当てることができず、管理アクセス接続も役に立たなくなるため、SQLサーバーは応答しなくなります。

メモリ不足が原因で、.NETアプリケーションでタスクスケジューラのハングアップが実際に発生しました。ありがたいことに、いくつかのエラーの後でキャッチできなかったいくつかのスレッドでOutOfMemoryExceptionをスローしたため、最終的にプロセスが終了し、サーバーが実際にハングアップしている原因を特定できました。

探しているものがわかったら、静的分析でバグを見つけるのは簡単でした。

0
Joshua