3

Web アプリケーション内で実行されるアクション、SQL サーバー エージェント ジョブ、データベースに対して手動でクエリを実行するアクションの監査証跡を作成しようとしています。トリガーを使用して、特定のテーブルの更新、挿入、および削除をキャッチしようとしています。

全体として、このプロセスは機能しています。たとえば、ユーザーが Web アプリケーションで更新を実行し、トリガーが更新されたデータを、アクションを実行した人のユーザー名を含む、定義した監査証跡テーブルに書き込みます。これは、Web アプリケーションまたは手動クエリの観点からは正常に機能しますが、特定のクエリを実行した SQL Server エージェント ジョブも多数あります。各エージェント ジョブは、同じユーザー名で実行されます。これも正常に機能し、ユーザー名をテーブルに正しく入力しますが、このクエリを呼び出すジョブが見つかりません。

私の現在の「解決策」は、トリガー時に現在実行されているジョブを見つけることでした。そのうちの1つが正しいものでなければならないからです。使用:

CREATE TABLE #xp_results 

    ( 
    job_id                UNIQUEIDENTIFIER NOT NULL,   
    last_run_date         INT              NOT NULL,   
    last_run_time         INT              NOT NULL,   
    next_run_date         INT              NOT NULL,   
    next_run_time         INT              NOT NULL,   
    next_run_schedule_id  INT              NOT NULL,   
    requested_to_run      INT              NOT NULL, -- BOOL   
    request_source        INT              NOT NULL,   
    request_source_id     sysname          COLLATE database_default NULL,   
    running               INT              NOT NULL, -- BOOL   
    current_step          INT              NOT NULL,   
    current_retry_attempt INT              NOT NULL,   
    job_state             INT              NOT NULL
    )   

INSERT INTO  #xp_results  
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, 'sa'  
SELECT @runningJobs = STUFF((SELECT ',' + j.name 
                FROM #xp_results r
                INNER JOIN msdb..sysjobs j ON r.job_id = j.job_id
                WHERE running = 1
                FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')

DROP TABLE #xp_results

テストのために特定のジョブを実行しましたが、動作しているように見えます。実行中のその他のジョブは にリストされますが@runningJobs、それを実行するジョブは記録されません。トリガーが実行されるまでに、ジョブは終了していると思います。

トリガーを開始するクエリを呼び出すジョブを見つける方法はありますか?

編集:SELECT上記のクエリを変更して、過去 2 分以内に実行された、または現在実行中のジョブを取得しようとしました。SQL クエリは次のようになります。

SELECT @runningJobs = STUFF((SELECT ',' + j.name 
            FROM #xp_results r
            INNER JOIN msdb..sysjobs j ON r.job_id = j.job_id
            WHERE (last_run_date = CAST(REPLACE(LEFT(CONVERT(VARCHAR, getdate(), 120), 10), '-', '') AS INT)
            AND last_run_time > CAST(REPLACE(LEFT(CONVERT(VARCHAR,getdate(),108), 8), ':', '') AS INT) - 200)
            OR running = 1
            FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')

ジョブを実行し、ジョブの実行中に上記のクエリを実行すると、正しいジョブが返されます。ただし、SQL Server エージェント ジョブを介して、または SSIS で手動で実行して SSIS パッケージを実行すると、@runningJobsは読み込まれず、単に が返されますNULL

だから私は今、それがSSISとのパーミッションの問題だと考えていmaster.dbo.xp_sqlagent_enum_jobsます. 他のアイデアはありますか?

編集#2:実際には、それがパーミッションエラーだとは思わないでください。このコードの下にステートメントがありINSERTます。パーミッション エラーの場合、INSERTステートメントは実行されないため、監査行はデータベースに追加されません。runningJobsそのため、フィールドが入力されていないだけで、データベースに行が追加されているためです。奇妙な時代。

編集#3:明確にしたいのですが、各仕事に行って何かを変更する必要のない解決策を探しています。これを実行可能な解決策にするには、仕事が多すぎます。

4

3 に答える 3

0

Update_Source などの追加の列をテーブルに追加し、すべてのソース アプリ (SSIS を含む) がテーブルを更新するときにそれを設定するようにします。

USER をその列の DEFAULT として使用して、必要な変更を最小限に抑えることができます。

于 2014-05-15T01:50:19.013 に答える