首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQLTransaction已完成错误

SQLTransaction已完成错误
EN

Stack Overflow用户
提问于 2013-03-08 12:07:41
回答 5查看 27.8K关注 0票数 14

我的应用程序中有一次出现了以下错误。

此SQLTransaction已完成,不再可用。

堆栈跟踪附在下面-它是关于Zombie CheckRollback的。

代码中的错误是什么?

注意:此错误只出现一次。

更新

来自MSDN - SqlTransaction.Rollback方法

如果连接终止或事务已在服务器上回滚,回滚将生成InvalidOperationException。

来自僵尸检查事务错误

我看到这个错误出现在各种应用程序中的最常见的原因之一是,在我们的应用程序中共享 SqlConnection。

代码语言:javascript
复制
public int SaveUserLogOnInfo(int empID)
{
        int? sessionID = null;
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            SqlTransaction transaction = null;
            try
            {
                transaction = connection.BeginTransaction();
                sessionID = GetSessionIDForAssociate(connection, empID, transaction);

                    //Other Code

                //Commit
                transaction.Commit();
            }
            catch
            {
                //Rollback
                if (transaction != null)
                {
                    transaction.Rollback();
                    transaction.Dispose();
                    transaction = null;
                }

                //Throw exception
                throw;
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }
            }
        }

        return Convert.ToInt32(sessionID,CultureInfo.InvariantCulture);

   }

堆栈跟踪

参考

  1. 什么是僵尸交易?
  2. 僵尸检查事务错误
  3. SqlTransaction已经完成
  4. http://forums.asp.net/t/1579684.aspx/1
  5. “此SqlTransaction已完成;它已不再可用。”配置错误?
  6. dotnet.sys-con.com -公开的SqlClient连接池
  7. 线程中止会留下僵尸事务和中断的SqlConnection
EN

回答 5

Stack Overflow用户

发布于 2013-03-08 12:18:02

您应该将一些工作留给编译器来为您将其包装在try/catch/finally中。

此外,如果在Rollback阶段出现问题,或者如果到服务器的连接中断,您应该期望Commit偶尔会抛出异常。因此,您应该将其包装在try/catch中。

代码语言:javascript
复制
try
{
    transaction.Rollback();
}
catch (Exception ex2)
{
    // This catch block will handle any errors that may have occurred 
    // on the server that would cause the rollback to fail, such as 
    // a closed connection.
    Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
    Console.WriteLine("  Message: {0}", ex2.Message);
}

这完全是从用于回滚方法的MSDN文档页复制的。

我看到你担心你会有僵尸交易。万一你粘上了,听起来不像你有问题。你的交易已经完成,你不应该再和它有任何关系了。如果你持有它,删除对它们的引用,并忘记它。

来自MSDN - SqlTransaction.Rollback方法

如果连接终止或事务已在服务器上回滚,回滚将生成InvalidOperationException。

重新抛出一个新异常,告诉用户数据可能没有保存,并要求她刷新和检查数据。

票数 8
EN

Stack Overflow用户

发布于 2013-03-08 12:12:57

注意:此错误只出现一次。

然后很难多说,可能只是// Other Code等人花了很长时间,整个事情都被杀了。可能是你的连接中断了,或者是管理员故意因为你的阻塞而把它杀死了。

代码中的错误是什么?

使它变得过于复杂;它可以简单得多:

代码语言:javascript
复制
using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    using(var transaction = connection.BeginTransaction())
    {
        try
        {
            sessionID = GetSessionIDForAssociate(connection, empID, transaction);
            //Other Code
            transaction.Commit();
         }
         catch
         {
            transaction.Rollback();
            throw;
         }
    }
}

更不用说出错的代码了。

票数 7
EN

Stack Overflow用户

发布于 2017-06-07 09:15:33

我使用下面的代码可以再现这个错误,我使用1000个任务执行Sql,在大约300个任务成功完成之后,大量关于timeout error的异常开始在ExecuteNonQuery()上发生,

然后,下一个错误This SqlTransaction has completed将发生在transaction.RollBack();上,其调用堆栈也包含ZombieCheck()

(如果单个程序对1000个任务的压力不够,您可以同时执行多个已编译的exe文件,甚至可以使用多台计算机执行一个DataBase。)

因此,我猜导致此错误的原因之一可能是连接中的错误,然后导致事务错误也会发生。

代码语言:javascript
复制
Task[] tasks = new Task[1000];
for (int i = 0; i < 1000; i++)
{
    int j = i;
    tasks[i] = new Task(() =>
         ExecuteSqlTransaction("YourConnectionString", j)
        );
}

foreach (Task task in tasks)
{
    task.Start();
}       

/////////////    

public void ExecuteSqlTransaction(string connectionString, int exeSqlCou)
{

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        SqlCommand command = connection.CreateCommand();
        SqlTransaction transaction;

        // Start a local transaction.
        transaction = connection.BeginTransaction();

        // Must assign both transaction object and connection
        // to Command object for a pending local transaction
        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
            command.CommandText =
                "select * from Employee";
            command.ExecuteNonQuery();

            // Attempt to commit the transaction.
            transaction.Commit();

            Console.WriteLine("Execute Sql to database."
                + exeSqlCou);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
            Console.WriteLine("  Message: {0}", ex.Message);


            // Attempt to roll back the transaction.
            try
            {
                transaction.Rollback();
            }
            catch (Exception ex2)
            {
                // This catch block will handle any errors that may have occurred
                // on the server that would cause the rollback to fail, such as
                // a closed connection.
                Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                Console.WriteLine("  Message: {0}", ex2.Message);

            }
        }
    }
}

此外,我发现如果连续提交两次,也会调用此异常。

代码语言:javascript
复制
       transaction.Commit();
       transaction.Commit();

或者,如果连接在提交之前关闭,也会调用此错误。

代码语言:javascript
复制
       connection.Close();
       transaction.Commit();

更新:

我觉得奇怪的是,我创建了另一个新表,并向其中插入了50万个数据,

然后在select * from newtable sql中使用100000个任务,同时运行5个程序,这一次会发生超时错误,但是当transaction.Rollback()没有调用SQLTransaction has completed error时。

但是,如果发生超时错误,跳入catch块,并且在catch块中再次执行transaction.Commit(),则会发生SQLTransaction has completed error

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15293673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档