死锁与记录

时间:2013-04-05 12:44:12

标签: sql sql-server-2008 logging deadlock

Web应用程序。 C#,SQL 2k8

在列表中,在执行实际的动态SQL之前会发生很多事情,并返回所需的记录。

最近我们为整个应用程序(死锁问题)添加了一些代码,包括事务提交,回滚和重试X次,整个9码。

这是一个很大的优点,我们真的需要它。

BUT

为了调试列表的任何可能的问题,我将动态SQL字符串保存在日志表中(仅在过去几周内不存储旧记录)

问题是:如果列表崩溃,现在没有日志。因为回滚的东西......

到目前为止,我最好的想法是将列表调用两次:

  1. “check” - 模式,将创建动态SQL,将其保存在LOG tbl中,但不会执行

  2. “list” - 模式将:

  3. 2a上。重新计算动态SQL

    2B。重用“check - mode

    创建的动态SQL

    2a或2b,不应该有巨大的性能问题,因为列表存储过程中最昂贵的部分是动态sql的实际执行。 “检查” - 模式是一些基本的字符串连接。

    死锁重试部分只会执行第二次db调用,这也很好!

    静止。 我不是这个想法中最开心的人。 我想知道是否有更好的方法来实现这一目标。

1 个答案:

答案 0 :(得分:1)

您可以使用(表)变量和TRY CATCH块在事务期间保存数据。回滚后保留变量。

如果您的翻译在存储​​过程中,则可能如下所示:

BEGIN TRY
    BEGIN TRAN

    DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = 'SELECT 1'

    RAISERROR('A',16,1)

    EXEC (@SQL)

    COMMIT

END TRY
BEGIN CATCH
    ROLLBACK
    SELECT @SQL --WRITE TO LOG TABLE

END CATCH

如果您的交易在SP之外 - 在C#代码中(这通常是一个更好的主意),您可以使用RAISERROR将您的变量发送回应用程序以及发生的实际错误。像这样:

BEGIN TRY

    DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = 'SELECT 1'

    RAISERROR('A',16,1)

    EXEC (@SQL)

END TRY
BEGIN CATCH

    DECLARE @ErrorMessage NVARCHAR(4000)
    DECLARE @ErrorSeverity INT
    DECLARE @ErrorState INT

    SELECT 
        @ErrorMessage = 'Error: ' + ERROR_MESSAGE() + '; SQL: ' + @SQL,
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE()

    RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState)

END CATCH