web-dev-qa-db-ja.com

1つのメインジョブから複数のSQL Serverエージェントジョブを順番に呼び出す良い方法は?

順次実行する必要があるSQL Serverエージェントジョブがいくつかあります。実行する必要があるジョブの概要を維持するために、EXEC msdb.dbo.sp_start_job N'TEST1'を呼び出して他のジョブを呼び出すメインジョブを作成しました。 sp_start_jobは即座に終了しますが(ジョブステップ1)、次のジョブを呼び出す前に、ジョブTEST1が終了するまでメインジョブを待機させます。

そのため、ジョブが呼び出された直後に実行を開始し(ジョブステップ2)、メインジョブを強制的にサブジョブが完了するまで待機させる次の小さなスクリプトを記述しました。

WHILE 1 = 1
  BEGIN
    WAITFOR DELAY '00:05:00.000';

    SELECT *
    INTO   #jobs
    FROM   OPENROWSET('SQLNCLI', 'Server=TESTSERVER;Trusted_Connection=yes;',
           'EXEC msdb.dbo.sp_help_job @job_name = N''TEST1'',
           @execution_status = 0, @job_aspect = N''JOB''');

    IF NOT (EXISTS (SELECT top 1 * FROM #jobs))
      BEGIN
        BREAK
      END;

    DROP TABLE #jobs;

  END;

これは十分に機能します。しかし、私はよりスマートで安全な感じを得ました(WHILE 1 = 1?)ソリューションは可能なはずです。

私は以下のことに興味があります。いくつかの洞察を提供してください。

  • このアプローチの問題は何ですか?
  • これを行うためのより良い方法を提案できますか?

(私はこの質問を StackOverflow に最初に投稿しました。これは、コードの改善に焦点を合わせていたためです。それでも有効です。しかし、私が思うに、ここにいる人は、なぜ私が試してはいけないのかについて、もっと賢明なことを言うでしょう。私が今行っている方法でこれを行うか、良い代替案を提供します。)

EDIT(7月25日)
スクリプトに関する問題を指摘する回答の数が少ないため、私のスクリプトにはそれほど問題はないようです:-)この種のスクリプトの代替手段は、これらのために設計されたツールを使用することですタスク(SQL Sentry Event Managerまたは...など)-またはそのようなツールを自分で作成する。現在の会社ではそのようなツールを購入することはないので、ここではスクリプトのみを使用します。

11
user5147

免責事項:私はSQL Sentryで働いています。

私たちの SQL Sentry Event Manager 製品には、ジョブをチェーン化し、さまざまなワークフローの順序でジョブを配置するための機能が組み込まれています。

私が入社する前の何年か前に、SQL Sentryを使い始めました。まさにこれを行うためです。私が欲しかったのは、運用環境でのバックアップが完了した直後にテストサーバーで復元ジョブを開始する方法でした。

私が最初に実装したのは、バックアップジョブの開始時刻と復元の開始時刻の間の単なるバッファでした。これは完全に簡単なことではありませんでした。バックアップ時間は変動するため、バッファは、たとえそれが可能であったとしても、リストアが開始されなかった無駄な時間を私たちに残しました。そして、時々バッファが十分ではなかった。

次に実装したものは、あなたが持っているものに似ていました-スケジュールされたバックアップの直後に開始するジョブをテストサーバーに書き込み、ポーリングを続けてジョブがいつ終了したかを確認しました。その後、テストサーバーのテーブルを更新するバックアップジョブに2つ目の手順が追加されました。それほど大きな違いはありませんが、復元ジョブは、リモートでジョブ履歴を監視するのではなく、ローカルでテーブルを監視するだけで済みました。これを思い出すと、そのテーブルでsp_start_jobを呼び出すトリガーになった可能性があるため、ジョブをn分ごとに実行する必要がありませんでした(またはまったくスケジュールする必要がありませんでした)。

最終的な解決策は、ジョブをチェーン化することでした...サーバーAでのバックアップが完了すると、イベントマネージャーはサーバーBで復元ジョブを開始します。そして、3番目のジョブと4番目のジョブ、または何をすべきかに基づく条件付きロジックがある場合ジョブが失敗したときと成功したときなどの場合、これはすべて説明できます。ワークフローデザイナーは、SSISをかなり思い出させます。

enter image description here

もちろん、私が説明している基本的なメカニズムはロケット手術ではありません。あなたが座ってそれをしたなら、あなたは自分でこのタイプの連鎖ラッパーを書くことができます。必要のない代替手段を1つ提供するだけです。

9
Aaron Bertrand

あなたのアプローチの主な問題は、何かが起こるまで(それはひどく長い時間かもしれないし、まったく起こらないかもしれない)継続的にループしなければならず、それはまったく正しく感じられないことです。これが、あなたが質問をしていると思います。

では、データ駆動型のアプローチを使用して問題を解決してみませんか?たとえば、各ジョブが開始および終了するときに書き込む「監査」テーブルを作成します。

ジョブ名|開始時間|終了時間
 --------- + ------------------- + ------------- ----- 
 Test1 2012-07-26 07:30 2012-07-26 07:35 

すべてのジョブとそれらを実行する必要がある順序をリストする「処理」テーブルを作成します。

ジョブ名|実行順序
 --------- + --------- 
 Test1 | 1 
テスト2 | 2 
テスト3 | 3 

監査テーブルに挿入トリガーを作成します。これにより、ジョブが完了して監査レコードが挿入されたときに、トリガーが次のジョブを処理テーブルに(実行順で)クエリし、それを起動します。

このアプローチの利点は次のとおりです。

  1. 開発と保守はかなり簡単です。
  2. コード行を変更せずに、処理テーブルを介して新しいジョブを追加したり、既存のジョブの順序を変更したりできます。
  3. 監査テーブルは、物事がいつ起こったかについてある程度の可視性を提供します。
  4. CPUサイクルを無駄にしません。トリガーは、何かが発生したときにのみ起動します。
  5. それfeels正しい????

HTH

2
paco