ストアドプロシージャを起動し、完了するのを待たずにすぐに戻ることはできますか?


41

ユーザーが手動で実行して、1日を通して常に使用されるレポートの更新された数値を取得できるストアドプロシージャがあります。

この最初のストアドプロシージャから取得した数値に基づいているため、最初のストアドプロシージャの実行後に実行する必要がある2番目のストアドプロシージャがありますが、実行に時間がかかり、別のプロセスのためです。この2番目のストアドプロシージャが実行されるまで、ユーザーを待機させます。

1つのストアドプロシージャで2番目のストアドプロシージャを開始し、結果を待たずにすぐに戻る方法はありますか?

SQL Server 2005を使用しています。


ストアドプロシージャはどのように呼び出されますか?ASP.NET Webアプリケーション?SSRS?
Mr.Brownstone


@ Mr.Brownstone通常はASP.Net Webアプリケーションから呼び出されますが、複数のWebアプリケーションから呼び出されることもあります。再確認する必要があります。また、SSRSから手動で実行されることもあります。
レイチェル

@MartinSmith私は過去にSQLサービスブローカーで働いたことがありますが、もっと簡単な方法があることを望んでいました。これほど単純なものの、このような複雑なセットアップのようです。
レイチェル

1
@MartinSmithそれは私が考えていたものです-また、SSRSについてはあなたができませんが、あなたができることはアプリケーションにレポートビューアを組み込み、その中にあなたのrdlを移動することです-そのように非同期呼び出しを行うことが可能ですレポートも同様です。
Mr.Brownstone

回答:


27

これを実現する方法は複数あるように見えますが、SQLジョブでプロシージャを設定し、ストアドプロシージャから非同期sp_start_jobコマンドを使用して開始するというMartinの提案が最も簡単な方法であることがわかりました。

EXEC msdb.dbo.sp_start_job @job_name='Run2ndStoredProcedure'

ストアドプロシージャにパラメーターを指定する必要がないため、これは私だけに有効です。

状況に応じて機能するその他の提案は次のとおりです。

  • MartinSebastianなどのSQL Service Brokerを使用することをお勧めします。設定とその仕組みの学習の複雑さを気にしない場合、これはおそらく最良の提案です。
  • Mr.Brownstoneが提案したように、ストアドプロシージャの実行を担当するコードでプロセスを非同期に実行します。

    悪い考えではありませんが、私の場合、ストアドプロシージャは複数の場所から呼び出されるため、それらすべての場所を見つけて2番目のプロシージャも呼び出すようにすることは実用的ではないように思われました。また、2番目のストアドプロシージャは非常に重要であり、実行するのを忘れると、当社にとって大きな問題が発生する可能性があります。

  • 1番目の手順でフラグを設定し、Jimboが提案したように、そのフラグを確認し、設定されている場合は実行する定期的なジョブを設定します。私は、数分ごとに継続的に実行され、変更をチェックするジョブの大ファンではありませんが、状況に応じて検討する価値のあるオプションです。

3
見てい非同期プロシージャの実行のService Brokerを使用してすぐに使用たとえば。sp_jobよりも優れている点は、Express Editionで動作し、完全にDBが含まれていることです(MSDBジョブテーブルに依存しません)。後者は、DBMフェイルオーバーおよびHA / DRリカバリで非常に重要です。
レムスルサヌ

シュート、マーティンが同じ記事をリンクしているのを見る。フェイルオーバー/ DR引数についてはコメントを残します。
レムスルサヌ

@RemusRusanu:まあ、それはService Brokerに関する最高の情報源の1つですが、すでに知っていると思います;-)。
マリアン

@Rusanuからのリンクは気に入りましたが、応答のないものが必要でした(この問題に一致すると思います)。私はabamacus.blogspot.com/2016/05/で
そろばん

また、SQLエージェントジョブを開始しようとするとEXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.、Azure上にService BrokerもSql Agentも存在しないため失敗します。10年半の人々が尋ねた後、Microsoftが追加を拒否する理由はわかりませんEXECUTE ASYNC RematerializeExpensiveCacheTable
イアン・ボイド

8

キューでのアクティベーションと一緒にService Brokerを使用できます。これにより、プロシージャコールのパラメータをキューに投稿できます。これには、挿入と同じくらい時間がかかります。トランザクションがコミットされ、場合によっては数秒後に、アクティベーションはレシーバープロシージャを非同期で自動的に呼び出します。wuoldだけではなく、キューのパラメーターを取得して必要な作業を行う必要があります。


7

この古い質問は、より包括的な答えに値します。これらのいくつかはここの他の回答/コメントで言及されていますが、OPの特定の状況では機能する場合と機能しない場合がありますが、SQLからストアドプロシージャを非同期に呼び出すことを求めている場合は機能する場合があります。

単に完全に明示するために、TSQLには(それ自体では)他のTSQL操作を非同期に起動する機能はありませ

それはあなたがまだ多くのオプションを持っていないという意味ではありません:

  • SQLエージェントジョブ:複数のSQLジョブを作成し、必要な時間に実行するようにスケジュールするか、を使用して「マスターコントロール」ストアドプロシージャから非同期に開始しますsp_start_job。プログラムで進捗を監視する必要がある場合は、各ジョブがカスタムJOB_PROGRESSテーブルを更新することを確認してください(または、グレゴリーA.ラーセンによるこの優れた記事でxp_sqlagent_enum_jobs説明されているように、文書化されていない機能の使用が完了したかどうかを確認できます)。異なるプロセスで同じストアドプロシージャを実行している場合でも、並列プロセスを実行するのと同じ数の個別のジョブを作成する必要があります。
  • SSISパッケージ:より複雑な非同期シナリオの場合は、単純な分岐タスクフローでSSISパッケージを作成します。SSISは、これらのタスクを個別のspidで起動し、SQLはこれを並行して実行します。SQLエージェントジョブからSSISパッケージを呼び出します。
  • カスタムアプリケーション:選択した言語(C#、Powershellなど)で、その言語が提供する非同期メソッドを使用して、シンプルなカスタムアプリケーションを作成します。各アプリケーションスレッドでSQLストアドプロシージャを呼び出します。
  • OLEオートメーション:SQLで、sp_oacreatesp_oamethodを使用して、Gregory A. Larsenによるこの記事で説明されているように、お互いにストアドプロシージャを呼び出す新しいプロセスを起動します。
  • Service Brokerこの記事の非同期実行の良い例であるService Brokerの使用方法を調べてください
  • CLR並列実行:CLRコマンドParallel_AddSqlを使用し、Alan Kaplanによるこの記事のParallel_Execute説明に従ってください(SQL2005 +のみ)。
  • スケジュールされたWindowsタスク:完全を期してリストされていますが、私はこのオプションのファンではありません。

私なら、おそらくより単純なシナリオでは複数のSQLエージェントジョブを使用し、より複雑なシナリオではSSISパッケージを使用するでしょう。

あなたの場合、SQL Agentジョブの呼び出しは、簡単で管理しやすい選択のように聞こえます。

最後のコメント:SQLは、可能な限りいつでも個々の操作を並列化しようとします*。これは、2つのタスクを交互に実行するのではなく、同時に実行しても、それがより早く終了するという保証がないことを意味します。実際に何かを改善するかどうかを注意深くテストします。

8つのタスクを同時に実行するDTSパッケージを作成した開発者がいました。残念ながら、4 CPUサーバーのみでした:)

*デフォルト設定を前提としています。これは、サーバーの最大並列度またはアフィニティマスクを変更するか、MAXDOPクエリヒントを使用して変更できます。


6

はい、1つの方法:

  1. 最初のストアドプロシージャが完了すると、2番目のストアドプロシージャの実行に必要なすべての情報を含むレコードが挿入されます。
  2. 2番目のストアドプロシージャは、ジョブとして、1分ごと、または決めた時間に実行されます。
  3. 挿入されたレコードをチェックし、処理を行い、レコードを完了としてマークします

これは、ストアドプロシージャの実行を、実行中のジョブの数に制限します。一度に1つのクライアントからのみ呼び出すようにしたい場合は、複数のクライアントが同じプロシージャを同時に呼び出すことができます。 。また、クライアントは、フラグが設定されているかどうかを確認するためにデータベースを繰り返しポーリングすることなく、ジョブが完了したことをどのように知るでしょうか?
Mr.Brownstone

1
@ Mr.Brownstone-ジョブは、実行時に異なるストアドプロシージャ呼び出しによってキューに入れられた複数の未処理のタスクを処理できる可能性があります。ストアドプロシージャはsp_start_job、必要に応じて呼び出したり動的にジョブを作成したりして、毎分ポーリングを回避することもできますが、その場合の複雑さはおそらくサービスブローカーほど簡単ではないことを意味します。
マーティンスミス

@MartinSmithこの2番目のストアドプロシージャは、1番目のプロシージャの番号と正しく同期されないという問題が見つかるまで毎晩実行されていたため、実際には既にジョブがセットアップされています。最初のストアドプロシージャからジョブを開始した場合、非同期で実行され、すぐにSPから戻りますか?
レイチェル

@レイチェル-はい。sp_start_jobすぐに戻ります。ただし、必要なアクセス許可を思い出せません。
マーティンスミス

1
大きなセキュリティホールを開けたくない場合、別のプロシージャ/データベースからジョブを開始することはかなり複雑な問題です。Erland Sommarskogには、組み合わせる必要のあるさまざまな手法に関する記事があります。sommarskog.se / grantperm.html ただし、完全なソリューションはありません。
セバスチャンマイネ

1

もう1つの可能性は、監査テーブルの完了時に1番目のストアドプロシージャが監査テーブルに書き込み、監査テーブルに書き込まれるときに2番目のストアドプロシージャを起動するトリガーを配置することです。継続的にポーリングする必要はなく、追加のSQL Serverエージェントジョブも不要です。


3
最初のストアドプロシージャは、監査テーブルへの挿入が完了するまで返されず、トリガーの実行が完了するまで発生しません(2番目のストアドプロシージャへの呼び出しを含む)
Martin Smith

1
トリガーの使用は既に検討しましたが、トリガーは非同期ではなくINSERTor UPDATEステートメントと同期して実行されるため、Martinは、1番目のプロシージャが2番目のプロシージャが戻るまで待機することになります。
レイチェル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.