从存储过程记录SQL Server错误

Joe*_*moe 9 sql-server

我们的应用程序是Windows服务(用C++编写的本机.EXE),它调用SQL Server中的存储过程.在大多数情况下,存储过程中的错误(在90%的情况下,这些错误意味着我们的业务逻辑中存在错误)被重新抛出作为异常并被我们的服务捕获.然后,它们将在运行我们服务的计算机上的应用程序事件日志中登录.

但是,我现在需要在存储过程中记录SQL Server本身的一些错误.

遵循我们用于服务的范例,我想我可以使用xp_logevent在事件日志中保存错误信息.

这是记录SQL Server错误的推荐方法吗?

FWIW我使用的是SQL Server 2008

daw*_*ber 8

如何

您始终可以使用RAISEERROR()WITH LOG.记录到Windows应用程序日志和SQL错误日志.请注意,严重性级别在此处是关键.有一些限制和安全注意事项,但您也可以获得其他一些功能.BOL中的更多细节:http: //msdn.microsoft.com/en-us/library/ms178592.aspx

你应该的吗?

我的意见是你不应该将任何内容记录到SQL错误日志中,除非它是由SQL服务器本身生成的.多种原因:

  1. 如果您的IT或DBA使用日志分析器或任何其他工具,它可能会在应用程序问题上发出警报,而不是服务器问题(这是他们试图捕获的).
  2. 我从来没有发现从SQL服务器中解析错误日志,我并不是特别喜欢SSMS的做法.

我的建议

使用通用日志记录存储过程写入某个错误日志表.一个非常好的模式是

BEGIN TRY
...do your stuff
END TRY
BEGIN CATCH
  get the ERROR_LINE(), ERROR_MESSAGE() and friends
  execute generic logging procedure
END  CATCH
Run Code Online (Sandbox Code Playgroud)

作为奖励,您可以在日志记录过程中使用SSSB使其异步并且不会妨碍主逻辑流程

  • @Joe SSSB是Sql Server Service Broker (2认同)

use*_*167 7

我发现这是跟踪SQL Server错误的有用方法。首先,创建一个表来存储错误:

CREATE TABLE utiliity.dbo.ProcedureLog
(
 LogDate     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
 DatabaseID    INT,
 ObjectID    INT,
 ProcedureName      NVARCHAR(400),
 ErrorLine    INT,
 ErrorMessage       NVARCHAR(MAX),
 AdditionalInfo     NVARCHAR(MAX)
);
GO
CREATE CLUSTERED INDEX cx_LogDate ON dbo.utiliity.dbo.ProcedureLog(LogDate);
GO
Run Code Online (Sandbox Code Playgroud)

然后创建一个存储过程,以在发生错误时调用:

CREATE PROCEDURE sp_CallProcedureLog
 @ObjectID       INT,
 @DatabaseID     INT = NULL,
 @AdditionalInfo NVARCHAR(MAX) = NULL
AS
BEGIN
 SET NOCOUNT ON;

 DECLARE 
  @ProcedureName NVARCHAR(400);

 SELECT
  @DatabaseID = COALESCE(@DatabaseID, DB_ID()),
  @ProcedureName = COALESCE
  (
   QUOTENAME(DB_NAME(@DatabaseID)) + '.'
   + QUOTENAME(OBJECT_SCHEMA_NAME(@ObjectID, @DatabaseID)) 
   + '.' + QUOTENAME(OBJECT_NAME(@ObjectID, @DatabaseID)),
   ERROR_PROCEDURE()
  );

 INSERT utiliity.dbo.ProcedureLog
 (
  DatabaseID,
  ObjectID,
  ProcedureName,
  ErrorLine,
  ErrorMessage,
  AdditionalInfo
 )
 SELECT
  @DatabaseID,
  @ObjectID,
  @ProcedureName,
  ERROR_LINE(),
  ERROR_MESSAGE(),
  @AdditionalInfo;
END
GO    
Run Code Online (Sandbox Code Playgroud)

最后,在您要记录错误的存储过程中:

BEGIN TRY
   ... execute SQL commands here
END TRY
BEGIN CATCH
    DECLARE @msg NVARCHAR(MAX);
    SET @msg = 'Something went horribly wrong.  Error number = ' + ERROR_NUMBER();
    EXEC utiliity.dbo.sp_CallProcedureLog 
    @ObjectID       = @@PROCID,
    @AdditionalInfo = @msg;

    DECLARE @ErrorMessage NVARCHAR(MAX);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT 
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE();

    -- Use RAISERROR inside the CATCH block to return error
    -- information about the original error that caused
    -- execution to jump to the CATCH block.
    RAISERROR (@ErrorMessage, -- Message text.
               @ErrorSeverity, -- Severity.
               @ErrorState -- State.
            );               
END CATCH 
Run Code Online (Sandbox Code Playgroud)

这是我的资料来源:http : //www.mssqltips.com/sqlservertip/2003/simple-process-to-track-and-log-sql-server-stored-procedure-use/http://msdn.microsoft。 com / zh-CN / library / ms178592(SQL.105).aspx。HTH。