2011-06-15 797 views
32

我一直在为此工作了大约一天半,并且搜索了大量的博客和帮助网络上的文章。我发现了几个与这个错误有关的问题,但我认为它们不适用于我的情况(或者在某些情况下,不幸的是,我无法很好地理解它们来实现:P)。我不确定我能够很好地描述这一点,以获得帮助...但这里有:“此SqlTransaction已完成;它不再可用。”...配置错误?

我们有一个.NET应用程序来跟踪我们的资源。有一个导出功能可将资源复制到时间跟踪系统和计费系统;这将访问链接到时间和账单数据库的存储过程。

我最近将计费系统数据库移至新服务器(原始服务器:Server 2003 SP2,SQL 2005;新服务器:Server 2008 R2,SQL 2008 R2)。我有一个指向2008数据库的链接服务器。我更新了存储过程以指向2008服务器,然后出现了有关MSDTC和RPC的错误(http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html)。我在链接服务器上启用'rpc/rpc out'并将MSDTC设置为允许网络访问(如下所示:http://www.sqlwebpedia.com/content/msdtc-troubleshooting)。

现在我收到了上述内容,当我尝试运行导出函数时:“此SqlTransaction已完成;它不再可用。”我觉得奇怪的是,当我刚刚运行存储过程(来自SSMS)时,它说它已成功完成。

有没有人见过这个?我错过了配置中的某些东西吗?我继续浏览相同的页面,我发现的唯一情况是在进行MSDTC更改后没有重新启动(在此提及:http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/7172223f-acbe-4472-8cdf-feec80fd2e64/)。

我可以发布部分或全部存储过程,如果它会帮助...请让我知道。

+0

http://stackoverflow.com/a/15923556/ 900284 – 2013-04-10 10:56:56

回答

31

我相信这个错误信息是由于“僵尸交易”。

查找可能发生的事务两次(或回滚两次,或回滚并提交等)的地方。 .Net代码是否在SP已经提交之后提交事务? .Net代码在遇到错误时是否回滚,然后尝试在catch(或finally)子句中再次回滚它?

这可能是一个错误条件永远不会在旧服务器上被击中,因此错误的“双滚回”代码从未被击中。也许现在你有一种情况,那里新服务器上的一些配置错误,现在错误的代码通过异常处理被击中。

你可以调试到错误代码?你有没有堆栈跟踪?

+2

看起来像是在正确的轨道上...我发现了另一个工具(dtctester),我原来的错误是由于配置错误(我以为我检查了新服务器上的防火墙...猜这就是我得到的假设)。看起来像我的新错误符合你的意思,“EXECUTE后的事务计数表示COMMIT或ROLLBACK TRANSACTION语句丢失。前一个计数= 1,当前计数= 2。”我将不得不多做一点挖掘并回复你。 – 2011-06-15 14:44:46

+2

我假设代码中有重复的内容......我在存储过程中注释了回滚事务,它看起来像现在一切正常。我在等待用户测试,但它已经超过了之前出现错误的地步。 :)感谢您的输入! – 2011-06-15 15:03:25

3

我最近遇到过类似的情况。要在任何VS IDE版本中进行调试,请从调试(Ctrl + D,E)中打开异常 - 针对列“Thrown”检查所有复选框,然后以调试模式运行应用程序。我意识到其中一个表没有在新数据库中正确导入,所以内部的Sql Exception导致连接中断,从而导致这个错误。

故事的主旨在于,如果以前的工作代码的新数据库返回此错误,这可能是数据库模式缺失问题,通过上述的调试尖端实现,

希望它能帮助, HydTechie

+0

感谢您的提示,通过一个真正的巴洛克式(车轮内轮子.....)传统应用程序,这有助于缩小问题 – orgtigger 2014-05-28 16:47:30

4

最近,我在一个新的连接管理器中进行了重构之后,有了这个。一个新的例程接受一个事务,以便它可以作为分批的一部分来运行,问题是与使用块:

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null) 
{ 
    using (transaction.Connection) 
    { 
    using (transaction) 
    { 
     return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure); 
    } 
    } 
} 

看起来好像外使用被关闭底层连接从而任何试图提交或回滚交易抛出了消息"This SqlTransaction has completed; it is no longer usable."

我删除了用户添加了覆盖测试,问题就消失了。

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null) 
{ 
    return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure); 
} 

检查任何可能在交易环境内关闭连接的情况。

2

在我的情况下,问题是包含在事务中的其中一个查询引发了一个异常,并且即使异常处理“优雅”,它仍然设法回滚整个事务。

我的伪代码就像:

var transaction = connection.BeginTransaction(); 
for(all the lines in a file) 
{ 
    try{ 
     InsertLineInTable(); // INSERT statement might fail and throw an exception 
    } 
    catch { 
     // notify the user about the error on line x and continue 
    } 
} 

// Commit and Rollback will fail if one of the queries 
// in InsertLineInTable threw an exception 
if(CheckTableForErrors()) 
{ 
    transaction.Commit(); 
} 
else 
{ 
    transaction.Rollback(); 
} 
1

我有同样的问题。发生此错误是因为连接池。当存在两个或更多的用户访问系统时,连接池也重用连接和转换。如果第一个用户执行提交或回滚,则该事务不会长期可用。

+1

这似乎也是我的问题,因为它只发生在多个用户在应用程序中。任何想法如何解决这一问题? – boilers222 2017-01-24 13:50:06

0

这里是检测僵尸交易

SqlTransaction trans = connection.BeginTransaction(); 

//some db calls here 

if (trans.Connection != null) //Detecting zombie transaction 
{ 
    trans.Commit(); 
} 

的方式反编译了的SqlTransaction类,你会看到下面的

public SqlConnection Connection 
{ 
    get 
    { 
    if (this.IsZombied) 
     return (SqlConnection) null; 
    return this._connection; 
    } 
} 

我注意到,如果连接被关闭,该transOP会变成僵尸,因此不能Commit。 对我而言,这是因为我在finally块中有Commit(),而连接在try块中。这种安排导致连接被丢弃并被垃圾收集。相反,解决方法是将Commit放入try块中。

1

同时检查从.NET应用程序对数据库执行的任何长时间运行的进程。例如,您可能呼叫的存储过程或查询没有足够的时间完成,可能会在日志中显示为:

  • 执行超时已过期。 完成操作或服务器没有响应之前超时的时间已过。

    • 此SqlTransaction已完成;它不再可用。

检查命令超时设置 尝试运行跟踪(探查),看看是什么在DB侧发生......

相关问题