例如,当死锁发生时,后面的 SQL 命令会成功执行,即使它们已经分配了回滚后的 SQL 事务。看来,它是由在 SQL Server 上创建的新隐式事务引起的。
有人可能期望 ADO.NET 会抛出一个异常,即命令正在僵尸事务上执行。但是,不会引发此类异常。(我认为这是 ASP.NET 中的一个错误。)此外,由于僵尸事务,最终会Dispose()
默默地忽略回滚。
任何想法,我如何确保没有人可以对隐式事务执行命令?或者,如何检查交易是僵尸?我发现Commit()
并Rollback()
检查了僵尸交易,但是我可以打电话给他们进行测试:)
我还发现阅读 IsolationLevel 也会进行检查,但我不确定transaction.IsolationLevel.ToString();
未来的优化器是否不会删除简单的调用。或者您知道任何其他安全方式调用 getter(不使用反射或 IL 发射)吗?
编辑:Remus Rusanu 指出这种情况通常不会发生。是的,这是真的。它通常发生在代码中存在错误时。在我们的例子中,finally 语句中有一些日志记录例程试图将失败存储到数据库中。现在,我正在尝试找到一种解决方案,以便将来检测此类错误。由于这些错误很难测试。如果 ADO.NET 会检查提供的事务是否为僵尸,则更容易发现此错误。我发现了两种可能性:
- 关闭隐式事务的创建 - 我不确定这是否可能。
- 确保在执行任何命令之前,检查僵尸事务将运行。