動的SQLバックアップコマンドにtry / catchを使用するときにエラーの詳細をログに記録する方法


10

try catchと動的SQLを使用するストアドプロシージャ内でバックアップコマンドを発行する場合、バックアップコマンドを直接実行する場合と比較すると、エラーメッセージは非常に一般的です。

SP内で試行/キャッチ:

    begin try
        execute sp_executesql @sql;  -- a backup command
    end try
    begin catch  
        print ERROR_MESSAGE();  -- save to log, etc.
    end catch

結果

50000:usp_Backup:117:BACKUP DATABASEが異常終了しています。

rawコマンドを発行するwheareas:

    backup DATABASE someDb to disk...

より詳細な結果:

ルックアップエラー-SQL Serverデータベースエラー:ファイル "H:\ FolderName \ Filename.bak:" 112で回復不可能なI / Oエラーが発生しました(ディスクに十分なスペースがありません。)

これらの詳細をストアドプロシージャ内の変数にキャッチする方法はありますか(ログを記録し、呼び出し元にパスバックし、ロジックを再試行します)?詳細はメッセージチャネルで送信されているようですが、SP内で利用できるようにしたいと思います。


:あなたはこの見たいかもしれstackoverflow.com/questions/5966670/...
8キロバイトを

回答:


13

BACKUP DATABASEエラーを生成すると、実際には2つ生成されます。残念ながらTRY/CATCH、最初のエラーをキャプチャすることはできません。2番目のエラーのみをキャプチャします。

失敗したバックアップの背後にある真の理由をキャプチャする最善の策は、バックアップを自動化することです SQLCMD(と-o、ファイルに出力を送信するために)SSIS、C#、PowerShellのその他のすべてのあなたのキャプチャを超えるはるかに大きい制御与えるそれらのすべてをエラーの。

コメントのSO回答は使用を示唆しています DBCC OUTPUTBUFFER -可能ですが、これは子供の遊びのようには見えません。Erland Sommarskogのサイトにあるこの手順を自由に楽しんでください。ただし、これをと組み合わせてもうまく機能しないようですTRY/CATCH

私がエラーメッセージをキャプチャできるように思えた唯一の方法 spGET_LastErrorMessageは、実際のエラーがスローされた場合です。TRY/CATCHエラーにラップすると、エラーが飲み込まれ、ストアドプロシージャは何もしません。

BEGIN TRY
  EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
  EXEC dbo.spGet_LastErrorMessage;
END CATCH

SQL Server <2012では、エラーを自分で再発生させることはできませんが、SQL Server 2012以降では可能です。したがって、次の2つのバリエーションが機能します。

CREATE PROCEDURE dbo.dothebackup
AS
BEGIN
  SET NOCOUNT ON;
  EXEC sp_executesql N'backup that fails...';
END
GO

EXEC dbo.dothebackup;
EXEC dbo.spGET_LastErrorMessage;

または2012年以降、これは機能しますが、目的を大幅に無効にします TRY/CATCHますが、元のエラーがまだスローされるため、のます。

CREATE PROCEDURE dbo.dothebackup2
AS
BEGIN
  SET NOCOUNT ON;
  BEGIN TRY
    EXEC sp_executesql N'backup that fails...';
  END TRY
  BEGIN CATCH
    THROW;
  END CATCH
END
GO

EXEC dbo.dothebackup2;
EXEC dbo.spGET_LastErrorMessage;

もちろん、どちらの場合でも、エラーはクライアントにスローされます。したがって、それTRY/CATCHを回避するために使用している場合、私が考えていない抜け穴がない限り、私はあなたが選択をする必要があると思います...ユーザーにエラーを与えて、詳細をキャプチャすることができますそれ、またはエラーと実際の理由の両方を抑制します。


とんでもないことですが、インターフェイス内の呼び出し元にコンテキストを提供したいだけの場合、ソマルスコグのアプローチは問題外とは思われません。別のプロセスを開始するよりも優れています。TRY / CATCH内では機能しないとおっしゃっていますか?
crokusek

@crokusek 1つのバリエーションを試しましたが、結果は空でした。今日はもう一発。
アーロンバートランド

エラーがない場合、LastErrorMessage()はセッションから以前のエラーの結果を取得しますか?次に、最後の2つのexecがスクリプトとして実行される場合、おそらく最初のexecがtry / catch内とcatch内でラップされ、変数を設定してから再スローする可能性があります。次に、変数が設定されている場合にのみ、LastErrorが呼び出されます。再スローが2番目の呼び出しをスキップしないと仮定します。2番目の呼び出しは、スクリプトコンテキスト内では通常正しいと思います。私が正しく理解した場合、SP内にすべてを配置することができないため、最終的にはこの方法を使用できない場合があります。ありがとう!
crokusek

2

まあ、これは古いスレッドであり、私が提案しようとしているのは複雑なハックであることはわかっていますが、誰かを助けることができる場合に備えて、これらのバックアップエラーがログに記録されるため、catchでxp_readerrorlogを使用できますブロックして関連メッセージ(エラーまたは情報)のログを取得します。xp_readerrorlog paramsを探し回ることができますが、簡単に言うと、この場合に役立つ検索文字列と開始時間フィルターを指定できます。これが再試行ロジックに役立つかどうかはわかりませんが、ログの情報またはエラーをキャプチャするために、私はこのようなものを思いつきました...

IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results (LogDate datetime,ProcessInfo nvarchar(100),LogText nvarchar(4000))
BEGIN TRY
SELECT @begintime = GETDATE()
EXEC sp_executesql @SQL --your backup statement string
INSERT #Results
EXEC  xp_readerrorlog 0, 1, N'backed up',@databasename,@begintime
SELECT @result = LogText from #Results where ProcessInfo = 'Backup' order by logdate desc
END TRY
BEGIN CATCH
INSERT #Results
EXEC  xp_readerrorlog 0, 1, N'Backup',@databasename,@begintime
SELECT @result = LogText from #Results where ProcessInfo = 'spid'+cast(@@SPID as varchar(6)) order by logdate desc
END CATCH
PRINT @result

HTH


これはいくつかの一般的なエラーに対してはうまく機能しますが、明らかにクライアントに直接スローされるだけのエラーがいくつかあります。sp_readerrorlogログには、「アプリケーションログ」を参照しているというメッセージが含まれます。「アプリケーション」とは、コマンドを発行している外部プロセスを意味していると思います。 SOリンク
crokusek 2015年

0

エラーの詳細をテーブルに記録できます。ログファイルを作成することもできますが、そのためにはCLRまたはxp_cmdshellが必要になる場合があります。データベースメールを送信することもできますが、これはスパムの問題を引き起こす可能性があり、適切なログではありません。

テーブルは最も単純です。

  1. エラーを格納するためのテーブルを作成する
  2. エラーテーブルに挿入するストアドプロシージャを作成する
  3. キャッチブロックでストアドプロシージャを呼び出す

以下のリンクで提供されているJeremy Kadlecの例をご覧ください。

http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/


3
問題はエラーの処理方法ではなく、内の一部のコマンドで適切なエラーメッセージが利用できないことですCATCH。これは、最後のエラーメッセージのみが返されるためERROR_MESSAGE()です
Aaron Bertrand
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.