SQL Server在连接丢失时会自动回滚更改吗?

6

我有一个SQL Server(server1)和Web服务服务器(server2)。server2拥有以下代码。其中从客户端获取结果请求并更新数据库。

 try
        {
            AppLogger.DebugFormat("Entered into save result - [{0}]", result.ID);
            int retry = 0;
            while (++retry <= 5)
            {
                try
                {
                    using (var oConnection = new SqlConnection("Connection string"))
                    {
                        oConnection.Open();
                        AppLogger.Debug("Saving data into db");
                        oConnection.Execute("storedproc1", new
                        {
                            param1 = Convert.ToInt32(result.value1),
                            param2 = Convert.ToInt32(result.value2),
                            param3 = result.value3=="Success",
                            param4 = result.vaue4
                        }, commandType: CommandType.StoredProcedure); 
                        AppLogger.DebugFormat("Save done with [{0}] try", retry);
                        break;
                    }
                }
                catch (SqlException sx)
                {
                    if (retry == 5)
                    {
                        AppLogger.Debug("sql exception occured");
                        throw;
                    }
                    else
                    {
                        AppLogger.ErrorFormat("Exception occurred [{0}] time(s), going to retry again after a minute", sx, retry);
                        System.Threading.Thread.Sleep(1000 * 60);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            AppLogger.Error("Unable to save result", ex);
            throw;
        }

我们的webservice服务器(Server2)遇到了蓝屏错误并停止工作。我们重新启动了服务器,并从应用程序中找到了以下日志信息。

 10:32:41.046 Entered into save result - 100023
 10:32:41.062 Saving data into db
 10:32:41.062 Save done with 0 try

 10:32:45.233 Entered into save result - 100024
 10:32:41.248 Saving data into db
 10:32:41.248 Save done with 0 try

但是SQL Server(server1)没有这个更新。

下面是我的存储过程:

Alter Procedure storedproc1
@Param1 int,
@Param2 int,
@Param4 varchar(2000),
@Param3 bit
AS
SET NOCOUNT ON

BEGIN   
     Declare @param5 varchar(30)
     select @param5=col1 from table1 where col2=@param1 and col3=@param2
     UPDATE table1 set col4=@param3, col5=@param4 where col2=@param1 and col3=@param2

     IF not exists (select 1 from table1 where col1 = @param5 and col5 is null and col4 is null)
     BEGIN
        UPDATE table2 set col2='statuschange'
        where col1 in (select distinct col6 from table1 where col1=@param5)
     END
END  

有人能指出应用程序服务器为什么会显示保存完成,而SQL服务器却没有更新吗?

在连接丢失时,SQL服务器是否会回滚更改?

顺便提一下,我使用Dapper与我的数据库进行交互。Log4net常见日志记录。

感谢您的时间, Esen

1个回答

2
一般来说,如果在连接丢失时有一个事务处于打开状态,那么该事务将完全回滚。另一方面,如果事务已提交,则其更改将即使在提交后立即发生服务器崩溃也能够幸存。
您的代码没有显示任何事务处理。如果执行SQL代码时没有显式事务,则每个语句都在自己的自动事务中运行。因此,每个完成的语句都将被保留。
您看到的行为表明正在使用事务并且未正确清除。这个问题与事务池一起可能导致意外行为。
跟踪此问题的一种方法是在using(var oConnection)块的开头执行SELECT @@TRANCOUNT;。如果返回的值比预期值高,则存在问题。它必须始终为0,或者如果dapper设置为在事务内部执行代码,则它必须始终为1。大于“默认”值的任何值都指向事务泄漏。

谢谢@Sebastian Meine,这不是一个经常发生的情况。在过去的六个月中只发生了一次。Transcount为0,我猜想这并不意味着在出现问题时它也是0。你的解释让我查看了这个数据库处理的其他程序和查询。一些存储过程确实对这个表使用了事务。很有可能这些存储过程也同时执行了。我正在清理事务混乱。由于我无法重现这个问题,我想清理将有助于未来。谢谢。 - Esen
在删除事务时要小心。代码被包装在事务中可能有很好的原因。(想想从一个帐户转移资金的典型例子。)但是,您可能希望研究如何统一处理它们。您要么希望在过程内进行事务管理而不在应用程序层中进行,要么全部在应用程序层中进行而不在过程中进行。并且-回顾您最初的问题-确保它们始终关闭(提交或回滚),无论它们如何打开并独立于潜在的错误情况。 - Sebastian Meine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接