我们在后端使用SqlTransaction类来访问存储在 MS-SQLServer 中的数据。
在某些情况下,我们肯定知道此事务没有更改任何数据(并且没有发生错误)。所以问题是:在这些情况下如何关闭交易?我们应该使用Commit()
or Rollback()
,还是不使用这两个功能或其他东西?目的是找到以“合理”的方式完成交易的最高效的方式。
我们在后端使用SqlTransaction类来访问存储在 MS-SQLServer 中的数据。
在某些情况下,我们肯定知道此事务没有更改任何数据(并且没有发生错误)。所以问题是:在这些情况下如何关闭交易?我们应该使用Commit()
or Rollback()
,还是不使用这两个功能或其他东西?目的是找到以“合理”的方式完成交易的最高效的方式。
我的建议
反过来想。
ROLLBACK
仅当您有理由撤消自事务开始以来的所有内容时才发出 a ,例如异常、错误状态或明确希望撤消所有内容。如果一切都按计划进行,那么您应该始终COMMIT
.为什么?
发出 a
ROLLBACK
将导致 SQL Server 撤消在事务中执行的任何工作。即使您“知道”SQL Server 没有更改数据,发出 a 也没有任何好处,
ROLLBACK
除非您希望 SQL Server 撤消更改,因为您担心无意的更改。如果您 100% 确定没有任何变化,那么我可以 100% 确信您应该发出 aCOMMIT
代替。如果您的代码所做的更改在技术上是更新的,但在逻辑上没有更改,那么 a
ROLLBACK
将是额外的工作。这是一个例子:
首先,让我们创建一个新鲜、干净和原始的新数据库。它像新床单一样干净清新:
那将是一张漂亮的大桌子。它可能不需要那么大。现在,让我们重新
CHECKPOINT
来看看事务日志。我得到 3 行返回。不管他们说什么,现在都不重要。现在,我们将在事务中进行更新,从逻辑上讲不会进行任何更改,但实际上会更新一堆行。对我来说,这将在 2 秒内运行,并更新 1892100 行,将状态设置为与当前状态完全相同的值。
现在,让我们再次查看事务日志:
? 对我来说,返回 2916 行——这些是 2916 条日志记录,在事务日志中记录了事务。你的旅费可能会改变。这些日志记录基本上是对 SQL Server 在您的事务期间所做的事情的衡量。所有这些日志记录都告诉我们 SQL Server 在该事务中做了一大堆工作。从逻辑上讲,它的结果为零,并且数据看起来与开始时完全相同......除了 SQL Server 实际上更新了这些行。
如果我
ROLLBACK
现在发布,SQL Server 将撤消这些更新。从逻辑上讲,这与不理会它们的结果相同,但是 SQL Server 只是按照它被告知的去做,它必须通过那些 2916 条日志记录来解开它所做的事情,并确保它让一切都保持原样在交易开始时。如果我改为发出 a
COMMIT
,SQL Server 只会说“OK。DONE!” 并记录,COMMIT
而不必解开已完成的工作。在我们开始之前,让我们删除我们创建的用于测试的数据库。
其他注意事项
如果我的
dbo.QueueStatus
桌子上有触发器怎么办?然后我的更新可能会引发一堆我没有意识到但仍然很重要的其他工作。您还让开发人员有责任了解、理解和维护在该事务中完成的工作为零的事实。未来对应用程序的更改可能会引入导致更改应该被持久化的代码路径——现在需要更新应用程序逻辑以知道不回滚。
记录呢?即使只是在开发周期中将一些内容放入日志表中以尝试解决问题只是临时日志记录,该日志记录也会被回滚。
COMMIT
or的使用ROLLBACK
必须取决于您在事务中执行的操作类型:COMMIT
COMMIT
如果您想了解更多详细信息,Microsoft 的事务文档非常值得一读,以了解不同类型的事务、何时使用它们以及它们的选项。
假设您的代码永远不需要更改、修复、重新利用、调试或审核,这是完全错误的。
如果你使用运算符、函数等(不仅在 SQL 中)是为了它们的副作用而不是为了它们的预期目的,那么下一个接触你的代码的开发人员会非常讨厌你。一段时间后,它也可能是你自己。
想象一下,您想稍后添加一些数据访问日志……祝您调试好运。
在你的代码中明确。意大利面条功能无论如何都会发展,不要帮助他们。
关于特定的提交/回滚问题:如果您真的、真的、真的在事务中什么都没改变,SQL Server 在任何一种情况下都不会做任何事情——它只会破坏事务上下文。