rob*_*cop 15 sql-server network
我最近对 100,000 条记录执行了更新查询。我意识到我在查询运行时犯了一个错误,并迅速拔掉了网络电缆。
是否更新查询
Aar*_*and 22
正如 Nick 和 Martin 所提到的,您的查询的最终状态取决于 SQL Server 在查询完成之前是否知道您的网络电缆已拔出。来自在线图书(尽管我觉得有趣的是,在2000、2005、2008和2008 R2中有与此相同的主题,但没有 2012 或 2014):
如果错误阻止了事务的成功完成,SQL Server 会自动回滚事务并释放事务持有的所有资源。如果客户端与数据库引擎实例的网络连接中断,则当网络通知实例中断时,连接的所有未完成事务都会回滚。如果客户端应用程序失败或者客户端计算机出现故障或重新启动,这也会中断连接,并且数据库引擎实例会在网络通知中断时回滚所有未完成的连接。如果客户端注销应用程序,任何未完成的事务都会回滚。
(顺便说一句,最后一句中的这个词连接可能是交易。我不知道如何回滚连接。)
类似地,SQL Server 在服务器意外关闭后的恢复过程中可能会撤消或重做事务,这取决于关闭时事务的状态。我已经看到人们使用这种策略来实现你想要做的事情(取消事务),当服务器再次启动时,大部分工作只是重做(所以他们下意识反应的净效应更接近)比他们预期的要零)。
因此,与其受制于这一点,不如在恐慌中做一些激烈的事情,例如拔掉网线或关闭机器,我建议您将来在对重要系统运行临时查询方面有更好的纪律。例如,而不是:
UPDATE dbo.sometable
-- where *oops* I forgot this part
Run Code Online (Sandbox Code Playgroud)
有这个:
BEGIN TRANSACTION;
UPDATE dbo.sometable
-- where *oops* I forgot this part
-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
然后,如果更新确实正确,您可以突出显示该COMMIT部分并运行它。如果不是,您可以冷静地突出显示该ROLLBACK部分并运行它。您甚至可以使用SSMS 工具包等加载项来编辑您的New Query模板以包含该样板。
现在,如果您运行查询然后不提交或回滚,它仍然会给您带来麻烦,因为现在您的事务正在阻止其他用户。但这比不可撤销地修改数据要好。
当然,一如既往,有一个您可以依赖的备份。
@Aaron 是正确的。在您发出命令之前创建交易是您最好的选择。如果您不记得这样做,那么一种选择是进入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!
Run Code Online (Sandbox Code Playgroud)
基本上,您正在权衡忘记BEGIN交易和搞砸某些事情,因为忘记COMMIT交易并在您将其打开然后离开一天时将其挂起。我做了测试,只是关闭了一个查询窗口,认为它会回滚我的事务,但是它确实提示我是否要提交或回滚事务。

小智 2
我认为这确实取决于:
如果在拔掉网线之前该命令已经到达服务器,该命令仍将继续正常执行。
如果你有一个 TransactionScope(在 .Net 中使用,不确定其他语言)来封装所有更新命令,那么只有在 transactionScope.Complete() 尚未执行时,你可能才能停止事务提交,但不能保证。 。