我最近对100,000条记录执行了更新查询。我意识到在查询运行时我犯了一个错误,并迅速拔下了网络电缆。
更新查询吗
- 停止处理并完全回滚?
- 继续处理以完成并提交?
- 停止处理,只保留部分目标行更新?
我最近对100,000条记录执行了更新查询。我意识到在查询运行时我犯了一个错误,并迅速拔下了网络电缆。
更新查询吗
Answers:
如Nick和Martin所述,查询的最终状态取决于SQL Server在查询完成之前是否知道您的网络电缆拔出情况。从在线丛书中(尽管我发现有趣的是,在2000年,2005年,2008年和2008 R2中有与此相对应的主题,但在2012年或2014年则没有):
如果错误阻止事务成功完成,则SQL Server将自动回滚该事务并释放该事务持有的所有资源。如果客户端与数据库引擎实例的网络连接断开,则当网络通知中断实例时,该连接的所有未完成事务都会回滚。如果客户端应用程序失败,或者客户端计算机关闭或重新启动,这也会断开连接,并且数据库引擎实例会在网络通知断开连接时回滚所有未完成的连接。如果客户端注销该应用程序,则所有未完成的事务都会回滚。
(顺便说一句,最后第二句中的“ 连接”一词可能是交易。我不知道该如何回滚连接。)
以类似的方式,SQL Server可能会在意外关闭服务器后在恢复过程中撤消或重做事务,这将取决于关闭时事务的状态。我已经看到人们使用这种策略来实现您想要做的事情(取消事务),并且当服务器再次启动时,很多工作都只是简单地重做了(因此,他们下意识的反应的净效果要近得多)达到比预期的零)。
因此,我建议您将来最好对在重要系统上运行即席查询有更好的纪律,而不是慌乱地做一些大胆的事情(例如拉动网络电缆或关闭机器)。例如,代替:
UPDATE dbo.sometable
-- where *oops* I forgot this part
拥有这个:
BEGIN TRANSACTION;
UPDATE dbo.sometable
-- where *oops* I forgot this part
-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;
然后,如果更新确实正确,则可以突出显示该COMMIT
零件并运行它。如果不是,您可以冷静地突出显示该ROLLBACK
零件并运行它。您甚至可以使用SSMS工具包之类的加载项来编辑New Query
模板以包括该样板。
现在,如果您运行查询然后又不提交也不回滚,它仍然可能使您遇到麻烦,因为现在您的事务正在阻止其他用户。但是,这比不可撤销地修改数据更好。
当然,像往常一样,有一个可以依靠的备份。
@亚伦是正确的。最好在命令之前创建事务。如果您不记得要这样做,那么一种选择是进入Tools-Options
设置并打开SET IMPLICIT_TRANSACTIONS
。一旦运行某些命令,这将自动启动事务。其中包括UPDATE
,DELETE
等等。这似乎是将要执行的所有命令的相当完整的列表"change"
。 SELECT
也包含在列表中并will
开始交易。您可以在此处看到启动此设置的事务的命令的完整列表。如果已经开始,则不会创建事务。现在不利的一面是,COMMIT
进行任何更改后您都必须记住。
注意:基于@Aaron的建议,我将再次强调这一点。
This is very important! You will have to remember to COMMIT after any change made!
基本上,您是在忘了BEGIN
一笔交易并弄乱了一些东西,而忘了COMMIT
一笔交易,如果您先将其保留为开盘,然后将其保留一天,则可以将其挂起。我确实测试了只是关闭一个查询窗口,以为它会回滚我的事务,但是确实提示我是否要提交或回滚该事务。
SELECT
将开始一笔交易(在您发布的链接中也有记录)
我认为这真的取决于:
如果在拔出网络电缆之前该命令已经到达服务器,则该命令仍将继续正常执行。
如果您有一个TransactionScope(用于.Net,不确定其他语言)用于封装所有更新命令,则只有在未执行transactionScope.Complete()但不能保证的情况下,才可以停止提交事务。 。