当连接关闭时,未提交的事务会发生什么?

48

它们是否会立即回滚? 还是在一段时间后回滚? 它们是否被保留在未提交状态?

如果使用连接池并且连接只是重置,那么行为是否相同?


相关链接:https://dev59.com/BW445IYBdhLWcg3wOnrW - Factor Mystic
3个回答

28

连接池应用时可保持打开状态。例如:命令超时会因客户端发送“abort”而保留锁定和 TXN(事务)。

两种解决方案:

  • 在客户端中进行测试:

    IF @@TRANCOUNT <> 0 ROLLBACK TRAN

  • 使用SET XACT_ABORT ON确保 TXN 被清除:Question 1Question 2

我总是使用 SET XACT_ABORT ON

来自SQL Team博客

请注意,在连接池中,仅关闭连接而不回滚将只返回连接到池中,并且事务将保持打开状态,直到稍后重用或从池中删除。这可能导致锁定保持不必要并引起其他超时和滚动块。

来自MSDN,“事务支持” 部分(我加粗了):

关闭连接时,它会被释放回池中,并根据其事务上下文放入适当的子部分中。因此,您可以关闭连接而不生成错误,即使仍有分布式事务待处理。这使您可以在稍后的时间提交或中止分布式事务。


2
连接池是在客户端进行的,因此如果客户端在不实际关闭连接的情况下内部中止连接,则应负责发出回滚或执行其需要解决此情况的任何操作。 - Fozi
@Fozi:除非你已经开启了SET XACT_ABORT ON。 - gbn
1
@gbn:SQL团队和MSDN的链接现在已经失效。 - user979222

8

未提交的更改在连接之外是不可见的,因此回滚的时间无关紧要。因此,事务最终会被回滚。


10
根据你的隔离级别,它可以挂起其他连接(等待提交/回滚),因此时间仍然很重要。 - Adam Batkin
4
正确,但强调的是“最终”,这是一件不好的事情 - gbn
我猜一旦TCP(或其他)连接被关闭/中断,它就会被回滚。关于连接池,请参见gbn的答案。 - Fozi
除非您在其他地方使用了NOLOCK或ISOLATION LEVEL READ UNCOMMITTED。 - tuseau
我正在使用ISOLATION LEVEL READ UNCOMMITTED,在新连接中会读取到我的未提交更改吗? - Barak

8

当会话关闭时,服务器将立即回滚任何未提交的事务。

ADO池负责在将事务返回给池之前清除任何未提交的事务。如果您处置了具有挂起事务的连接,则会回滚该事务。

客户端可以使用ADO API(SqlConnection.BeginTransaction)启动事务,也可以通过执行BEGIN TRANSACTION语句来启动事务。客户端和服务器之间的TDS协议具有特殊的令牌,通知客户端何时开始/提交事务,因此即使在T-SQL代码中启动它们,ADO也知道连接具有挂起的事务。


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