如何在事务中记录事件

时间:2011-09-07 14:28:39

标签: sql sql-server

我有一个SQL Server 2008 R2存储过程,它在TRANSACTION中运行一些INSERT和UPDATE。在每个语句之后,我需要在执行下一步之前记录刚刚发生的事情。

这是我的代码:

BEGIN TRY

    BEGIN TRANSACTION

        INSERT INTO... -- 1st statement
        INSERT INTO MyEventLog (EventDescription) VALUES ('Did Step 1') -- log

        UPDATE... -- 2nd statement
        INSERT INTO MyEventLog (EventDescription) VALUES ('Did Step 2') -- log

    COMMIT TRANSACTION

END TRY

BEGIN CATCH
    IF (@@TRANCOUNT<>0) ROLLBACK TRANSACTION
    EXEC LogError 'I got an error'
END CATCH

问题是:如果出现错误,事务将回滚所有语句 - 包括我需要的日志记录。如果发生错误,如何回滚交易但保留记录

4 个答案:

答案 0 :(得分:1)

我打算问你为什么要记录技术上没有发生的事件,因为事务将被回滚并且数据库将处于事务之前的状态。但后来我发现你可能只是想记录它以便知道它失败了,所以你可以解决潜在的问题,这是一个聪明的事情。

如果确实如此,最好的办法是回滚当前正在执行的整个事务,并使用LogError SP在另一个表中记录错误消息。这就是我使用的:

CREATE PROCEDURE [dbo].[Error_Handler]
@returnMessage bit = 'False'
WITH EXEC AS CALLER
AS
BEGIN

  DECLARE @number int,
    @severity int,
    @state int,
    @procedure varchar(100),
    @line int,
    @message varchar(4000)

  INSERT INTO Errors (Number,Severity,State,[Procedure],Line,[Message])
  VALUES (
    ERROR_NUMBER(),
    ERROR_SEVERITY(),
    ERROR_STATE(),
    isnull(ERROR_PROCEDURE(),'Ad-Hoc Query'),
    isnull(ERROR_LINE(),0),
    ERROR_MESSAGE())

  IF(@returnMessage = 'True')
  BEGIN
    select *
    from Errors
    where ErrorID = scope_identity()
  END
END

错误消息可以让您知道在哪个表中出现了什么问题,并且 应该足以解决问题。

答案 1 :(得分:1)

Logging messages during a transaction。有点令人费解:

但它确实允许您在事务期间记录消息,即使事务回滚,消息也会保留。记录顺序保留。

当一个程序失败但事务可以继续时(例如,处理批处理和一个项目失败时,您希望继续完成批处理的其余部分),您还需要使事务和存储过程发挥得很好。请参阅Exception handling and nested transactions

答案 2 :(得分:0)

如何将日志记录语句放入单独的事务中?

我把它放在CATCH块中:

BEGIN CATCH            
  IF (@@TRANCOUNT<>0) 
  ROLLBACK TRANSACTION           
  EXEC LogError 'I got an error'  
  BEGIN TRANSACTION
    INSERT INTO MyEventLog (EventDescription) VALUES ('Error Updating') -- log
  END TRANSACTION
END CATCH 

答案 3 :(得分:0)

事实证明,表变量不遵循事务语义。因此,您可以插入表变量,然后在catch块之后将表变量插入到日志表中。