4

SQL Server 2000には、外部の exe を呼び出す通常の (つまり、拡張されていない) ストアド プロシージャがあります。その exe は、SDK からの .dll をロードし、そこからいくつかのプロシージャ (つまり、Init、DoStuff、Shutdown) を呼び出します。

この外部 exe を使用する唯一の理由は、.dll を呼び出す拡張ストアド プロシージャを作成したくなかったからです。dll がクラッシュした場合 (可能性は低いですが)、SQL Server プロセスもクラッシュすると考えられていましたが、これは私たちが望んでいたことではありませんでした。外部exeを使用すると、そのexeだけがクラッシュします。

現在、SQL Server 2008にアップグレードし、それを呼び出す CLR ストアド プロシージャを作成して、exe を削除することを検討しています。もちろん、この SP は UNSAFE としてマークされます。そのための問題は、拡張 SP アプローチと比較して、そのようにすることは安全である (より安全である、十分に安全であるなど) か?

私がBOLで追い詰めた唯一の関連するものは次のとおりです。

UNSAFE を指定すると、アセンブリ内のコードが SQL Server プロセス空間に対して不正な操作を実行できるようになるため、SQL Server の堅牢性とスケーラビリティが損なわれる可能性があります。

、しかし、「堅牢性とスケーラビリティ」を求めているのではなく、安定性と物事を稼働させ続けることを求めているため、それが私の質問に答えるかどうかはわかりません。

PS: SP のアクセス許可を管理するときに不都合が生じるため、exe を削除したいと考えています (xp_cmdshell を含む SP を呼び出すと、突然適用されるものです)。

4

2 に答える 2

3

このコードは元々拡張ストアドプロシージャで使用されていたため、アンマネージコードのようです。管理されていないコードのバグは、プロセスを簡単にクラッシュさせる可能性があります。

CLR統合は、拡張ストアドプロシージャよりもはるかに堅牢ですが、コードはインプロセスで実行されるため、エラーによってSQLServerが停止または破損する可能性があります。(比較のために、理論的には、SAFECLRルーチンはSQLServerを破損することはできませんが、SQL Serverを完全に停止せずに、サーバーの可用性を低下させる問題を引き起こす可能性があります。)

基本的に、このシナリオでSQLServerをクラッシュさせない唯一の方法は次のとおりです。

  1. クラッシュする機能の使用は避けてください。
  2. バグのあるコードを修正します。
  3. 別のプロセスでコードを実行します(実行可能ファイルの起動、Windowsサービスの呼び出し、Webサービスの呼び出しなど)。この相互作用を実行するために、マネージ.NETDLLを作成できます。ほとんどの場合、それでも安全でない状態でロードする必要がありますが、適切に記述されていれば、実際には非常に安全です。
于 2009-07-04T13:20:38.453 に答える
1

そのための問題は、拡張された SP アプローチと比較して、そのようにすることは安全 (より安全、十分に安全など) でしょうか?

一般的にはい。つまり、OS プロセスにシェル アウトしている場合は、OS プロセスにシェル アウトしているということです。拡張ストアド プロシージャ API を使用してそれを行うことが、SQLCLR API よりも安全であるとは限りません。特に、クラッシュする可能性があるのがデータベースの外部にある OS プロセスである場合です。

もちろん、XP API は使ったことがないのでよくわかりませんが、次のことは知っています。

  • XP API は非推奨であり、これらのテクノロジのいずれかで実行できるすべての新しいプロジェクトを SQLCLR で実行することをお勧めします。
  • SQLCLR では、偽装を実行する機能 (SQLCLR オブジェクトを実行するログインが Windows ログインの場合) など、他の 2 つよりも細かい権限が許可されます。
  • SQLCLR API は、データベースとアセンブリの所有者 (つまり、AUTHORIZATION句で指定されたユーザー) の両方によってプロセス/メモリごとに分離されます。したがって、他のDBのSQLCLRオブジェクトに影響を与えることなく、あるDBのアセンブリに問題が発生する可能性があります(または、別のユーザーが所有するアセンブリがある場合は同じDBにありますが、実際には、ほとんどの人が単にデフォルトの を使用しますdbo)。

「堅牢性とスケーラビリティ」を求めているのではなく、安定性と物事を稼働させ続けることを求めているため、それが私の質問に答えるかどうかはわかりません。

Assembly が に設定されている場合、SQLCLR 内でできることは確かにありますUNSAFE

  • レジストリに書き込む可能性があります (SQL Server プロセスを実行しているログオン アカウントに付与されているアクセス、または SQLCLR 関数を実行しているログイン (偽装が有効で Windows ログインの場合) に応じて異なります)。
  • ファイルシステムへの潜在的な書き込み
  • システム上で実行されているプロセスと潜在的に相互作用する
  • 同じアセンブリ (そのユーザーが所有する、その DB 内の特定のアセンブリを意味します) から関数を実行する他の SQL Server SPID (つまり、セッション) とメモリを共有します。コンソール アプリや Windows アプリが独自の個別のメモリ空間を持つことに慣れていると予想外であるため、これはおそらく人々を最も逃れますが、ここでは、所有者ごとの DB ごとのアセンブリごとに単一の AppDomain であるため、そのコードを実行するすべてのセッションが共有されます。すべてのstatic変数。多くのコードは、AppDomain がプライベートであることを前提に記述されているため、静的変数に値を格納すると値がキャッシュされるため効率的ですが、SQLCLR では、2 つのプロセスが互いの値を上書きし、もう一方の値を読み取ると、予期しない動作が発生する可能性があります。セッションの値。
  • メモリリークの可能性。TimeZoneInfoホスト保護属性は、TimeZoneID 間の時間を変換するために使用するなど、これを行うことができる組み込みの .NET 機能を使用できないようにしようとしますが、ホスト保護属性はUNSAFEアセンブリには適用されません。
  • UNSAFE / FullTrust コード (Cooperative Multitasking と Preemptive) を実行する場合、SQLCLR メソッドを実行するスレッドが異なる方法で処理される可能性があります。UNSAFE スレッドは別の方法で管理されていることを読んだことがあると思いましたが、どこで読んだのかわかりません。ソースを探しています。

ただし、上記のすべてが述べられているように、外部 EXE を呼び出す場合は、独自の AppDomain があります。

したがって、できることは次のいずれかです。

  1. への SQLCLR ラッパーを使用して EXE を呼び出し続けますProcess.Start()。これにより、プロセス/メモリの分離、この EXE を呼び出すだけで誰も変更できない単一のストアド プロシージャへのアクセス許可をより簡単に制御できるようになります (少なくとも、SQLCLR コードを変更してアセンブリを再インストールする必要はありません)。

  2. 同じマシンに SQL Server Express のインスタンスをインストールし、そこに SQLCLR オブジェクトを読み込み、リンク サーバーを双方向 (現在の SQL Server インスタンスから新しい SQL Server Express インスタンスへ) に作成して、それらの間で簡単に通信できるようにします。これにより、SQLCLR の実行を隔離し、メインの SQL Server プロセスから遠ざけることができます。

もちろん、そうは言っても、これは実際にどれほどの懸念があるのでしょうか? つまり、プロセスが完全にクラッシュしてすべてがダウンする可能性はどれくらいあるでしょうか? 確かに不可能ではありませんが、通常、クラッシュによって CLR ホスト自体ではなく、AppDomain だけがダウンします。クラッシュはしないが、記述が不十分でメモリや CPU を大量に消費するコードは、人々が遭遇する問題になる可能性がはるかに高いと思います。

于 2016-04-08T07:06:22.740 に答える