数日ごとにSQL Serverインスタンスが予期せず終了し、再起動します。ログで、以下を参照してください。
.NET Framework共通言語ランタイムで致命的なエラーが発生しました。 SQL Serverをシャットダウンしています。 (イベントID 6536)。
終了する前に、次のようなメッセージが表示されます。
メモリ不足のため、AppDomain XXXにアンロードのマークが付けられています。
私は60のCLRストアドプロシージャを持っていますが、これは前任者から継承したものです。これらはすべて、少量のデータを使用する短いストアドプロシージャであると想定されています。 メモリ負荷の原因となっているCLRストアドプロシージャを見つけるにはどうすればよいですか?
私は走っています:
Microsoft SQL Server 2016(SP1-CU4)(KB4024305)-13.0.4446.0(X64)Jul Jul 2017 18:08:49 Standard Edition(64-bit)on Windows Server 2016 Standard 6.3(Build 14393:) (ハイパーバイザー)
Sqlservr.exeが予期せず終了する原因となるメモリプレッシャーを引き起こしているCLR Stored Procはどれですか。
SAFE CLRプロシージャはSQL Serverをクラッシュさせないため、CLRのマネージメモリの使用状況を調べても、根本的な原因につながる可能性はほとんどありません。
メモリリークのあるネイティブコードとやり取りする安全でないCLRコードがある可能性が高いです。したがって、サードパーティのネイティブコンポーネント(OleDBまたはODBCドライバ)など)の使用、またはP/InvokeまたはCOM Interopの使用については、CLRプロジェクトを参照してください。
野生のガチョウを追いかける前に、いくつかのことを指摘しておきます。
.NET/CLRは、カスタムSQLCLRコードを追加したことがなくても、SQL Serverによってさまざまな目的で使用されます。 FORMAT()
などの組み込み関数があり、CLRデータ型(Geography
、Geometry
、HierarchyID
)、変更追跡などの機能があります。など。 "CLR enabled"のサーバー構成オプションを無効にした場合でも、1つ以上の領域でCLRを引き続き使用できます。つまり、これがコードからのものであるとは限りません(カスタムコードが最初にチェックするのに最適な場合でも)。
メモリプレッシャーは、物理メモリが不足しているシステムの機能であり、カスタムCLRアセンブリの実際の使用とは関係ない場合があります。メモリ不足のためにアンロードのマークが付けられているアプリドメインに関するメッセージをログファイルで取得しても、そのアプリドメインで何が行われていたか、つまりアンロードの候補であるという以外の意味はありません。
次のDMVの_survived_memory_kb
_フィールドに注目してみてください。
_SELECT * FROM sys.dm_clr_appdomains;
_
それは解放されていないメモリの量であるべきだからです。もちろん、60個すべてのSQLCLRストアドプロシージャが同じアプリドメインにある場合、アプリドメインによって大量のメモリが保持されているという考えを証明または反証する場合を除いて、これは役に立たない可能性があります。
また、システムはどのくらい忙しいですか?システムがビジー状態の場合、ガベージコレクションが実行されないことがあります。その場合は、ガベージコレクションを実行するシンプルなCLR関数(単一のコマンド)を作成することで強制的に実行できます。この関数は、すべてを取り除くわけではなく、頻繁に呼び出す必要はありませんが、確実にいくつかの要素をクリアします。
最後に、リソースをロックするUNSAFE
コードである必要はありません。ネットワークやファイルシステムなどとやり取りする_EXTERNAL_ACCESS
_コードがある場合、.Dispose()
への呼び出しを介して明示的に、またはこれらのリソースが適切に破棄されていることを確認する必要があります。 using()
構文にラップされているオブジェクトのインスタンス化。外部リソースを適切に破棄しない場合、特にコードが大量に呼び出された場合、理論的には使用可能なすべてのハンドルを使い果たす可能性があります。