提交后回滚

Mar*_*tin 4 sql-server transaction rollback

我有多个数据库会话,由于应用程序冻结,其中一个会话一直在阻止其他会话。在多个会话上运行事务。由于其他会话的锁定请求超时,我需要终止头部阻止程序。杀死该会话后,其他用户报告数据丢失。我很确定他们已经提交了他们的交易,但他们似乎仍然被回滚了。他们甚至可以证明它,因为一些文档已经打印出来,但后来丢失了数据。

由于另一个会话的回滚,提交的事务是否有可能被回滚?我不这么认为,但在阅读COMMIT 文档后,我有疑问。它说:

如果@@TRANCOUNT 大于 1,COMMIT TRANSACTION 只会将 @@TRANCOUNT 减 1,并且事务保持活动状态。

阅读TRANCOUNT 文档,它说:

返回在当前连接上发生的 BEGIN TRANSACTION 语句的数量。

那么当前连接是否与会话相同,或者多个会话可以共享同一个连接(也许通过池)?如果他们可以分享,这与交易有什么关系?这些活动事务是否会在稍后甚至在提交之后回滚?

[编辑] 更清楚的是,一些用户没有得到锁定超时,因为他们的数据与头部拦截器没有冲突。他们提交了事务,但在杀死头部阻止程序后,这些事务似乎已回滚。

[更新 2018-03-29]发生新事件后,我有机会在问题发生时进行调查。事务日志得出结论,问题是一个从未提交的嵌套事务。导致问题的应用程序并未冻结,因此用户在关闭应用程序之前从未注意到它。那时他丢失了他的数据,因为事务被回滚了。我接受了可能的最佳答案,那是告诉我不可能回滚已提交事务的答案。我想这真的不可能,只是很难找到真正的问题。

gbn*_*gbn 12

通常,交易恰好是其中之一

  • 坚定的
  • 回滚

已提交的事务永远不会回滚。
这是所有 RDBMS 的运行方式,基于ACID 原则

现在,在一些不同的情况下,这条规则可能看起来已经被打破了。但它没有。

不过,在我们查看这些案例之前,不同的用户会话不共享连接。每个用户/客户端都有一个到 SQL 的连接,并且所有连接都彼此隔离。连接池对此没有影响。

保存点

您可以保存事务并回滚到此保存点,

也就是说,如果您使用保存点,您可以部分提交/回滚,但我从未见过任何人在现实生活中的代码中这样做。我不会再展开了。

嵌套事务

您可以嵌套事务,但它们并没有真正的意义
简单地说,即使@@TRANCOUNT 可以大于 1,SQL Server 也没有真正的嵌套事务。

  • 开始将@@TRANCOUNT 增加 1
  • 回滚会将@@TRANCOUNT 设置为零
  • 提交将@@TRANCOUNT 减一

更长的解释是在这个 SO answer