Останавливает ли отключение сети запрос?

13

Я недавно выполнил запрос на обновление 100 000 записей. Я понял, что допустил ошибку, пока выполнялся запрос, и быстро отключил сетевой кабель.

Есть ли запрос на обновление?

  1. остановить обработку и полностью выполнить откат?
  2. продолжить обработку до завершения и зафиксировать?
  3. остановить обработку и оставить обновленной только часть целевых строк?
Робокоп
источник
2
как только запрос попадет на сервер, он продолжится, если вы не отменили запрос на сервере.
JP Chauhan
1
Комментарий Мартина дает прямой ответ на ваш вопрос, robocop. Если сеть уведомит SQL Server о разъединении до того, как ваш запрос завершится, SQL Server выполнит откат. В противном случае, если запрос завершится до того, как SQL Server получит сообщение о разрыве сети, он будет зафиксирован. В любом случае (если вы написали один запрос на обновление) SQL Server не выполнит частичное обновление.
Ник Чаммас

Ответы:

22

Как упоминали Ник и Мартин, конечный статус вашего запроса зависит от того, знает ли SQL Server о подключении сетевого кабеля до завершения запроса. Из Books Online (хотя мне интересно, что существуют эквивалентные темы для этого в 2000 , 2005 , 2008 и 2008 R2 , но не 2012 или 2014):

Если ошибка препятствует успешному завершению транзакции, SQL Server автоматически откатывает транзакцию и освобождает все ресурсы, удерживаемые транзакцией. Если сетевое соединение клиента с экземпляром компонента Database Engine разорвано, все незавершенные транзакции для этого соединения откатываются, когда сеть уведомляет экземпляр об обрыве. Если происходит сбой клиентского приложения или если клиентский компьютер выходит из строя или перезапускается, это также разрывает соединение, и экземпляр компонента Database Engine откатывает все незавершенные соединения, когда сеть уведомляет его о разрыве. Если клиент выходит из приложения, все ожидающие транзакции откатываются.

(Кроме того, слово « соединения» во втором последнем предложении, вероятно, подразумевало транзакции . Я не знаю, как откатить соединение.)

Аналогичным образом, 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 Tools Pack, чтобы отредактировать New Queryшаблон, добавив этот шаблон.

Теперь это может привести к проблемам в том случае, если вы выполните запрос, а затем не будете выполнять фиксацию или откат, потому что теперь ваша транзакция блокирует других пользователей. Но это лучше, чем безвозвратно модифицировать данные.

И, конечно, как всегда, есть резервная копия, на которую можно положиться.

Аарон Бертран
источник
5
Это отличный совет, который устраняет корень проблемы OP, но на самом деле он не отвечает на вопрос о том, продолжался ли запрос или нет.
Ник Чаммас
3
Спасибо @Nick, моей мотивацией было устранить причину (которая подстегнула вопрос), а не симптом, но я обновил свой ответ.
Аарон Бертран
8

@ Аарон прав. Лучше всего создать транзакцию до того, как ваши команды. Если вы не можете вспомнить, что делать, то один из вариантов - войти в Tools-Optionsнастройку и включить SET IMPLICIT_TRANSACTIONS. Это автоматически запустит транзакцию, как только будут выполнены определенные команды. Это включает в себя UPDATEи DELETEт. Д. Это, кажется, довольно полный список любой команды, которая будет "change"что-то. SELECTтакже включен в список и willначать транзакцию. Вы можете увидеть полный список команд , которые начинаются завещание транзакции этого параметр здесь . Он не будет создавать транзакцию, если она уже запущена. Теперь минусом этого является то, что вам придется помнить об этом COMMITпосле внесения любых изменений.

ПРИМЕЧАНИЕ: на основе предложения @ Аарона я собираюсь еще раз подчеркнуть это.

This is very important!  You will have to remember to COMMIT after any change made!

В основном вы торгуете, забывая BEGINо транзакции, и что-то путаете, забываете COMMITо транзакции и зависаете, если оставляете ее открытой, а затем уходите на день. Я тестировал, просто закрывая окно запроса, думая, что он откатит мою транзакцию, однако он действительно подсказал мне, хочу ли я зафиксировать или откатить транзакцию.

введите описание изображения здесь

Кеннет Фишер
источник
На самом деле: SELECT будет начать транзакцию (которая также документированный в ссылке вы публикуемую)
a_horse_with_no_name
Спасибо @a_horse_with_no_name за это! Я не читал достаточно внимательно и ушел из старой памяти (это было явно неправильно).
Кеннет Фишер
1
Это полезный пост, но на самом деле он не отвечает на вопрос ОП о том, продолжался ли запрос или нет.
Ник Чаммас
2
Это было задумано как дополнение к ответу @ Аарона. Это было просто много, чтобы добавить комментарий.
Кеннет Фишер
2

я думаю, что это действительно зависит

если команда уже достигает сервера до того, как вы отсоедините сетевой кабель, она все равно будет продолжать выполняться в обычном режиме.

если у вас есть TransactionScope (используется в .Net, но не на других языках) для инкапсуляции всех команд обновления, вы, вероятно, можете остановить фиксацию транзакции только в том случае, если не выполнена транзакцияs.Somplete (), но без гарантии. ,

Rex
источник
2
Вы сказали: «Если команда уже достигает сервера до того, как вы отключили сетевой кабель, команда все равно будет продолжать выполняться в обычном режиме». Это противоречит странице BOL SQL Server, на которую Мартин ссылался выше. См. «Ошибки при обработке транзакции» .
Ник Чаммас
вы правы. с указанной транзакцией, команда будет автоматически откатываться. но, как мы поняли, когда транзакция не была указана явно, команда (пакетное обновление без транзакции) была выполнена полностью, даже когда мы остановили наше приложение посередине, что фактически разорвало соединение - но это не очень хороший пример, как время было, вероятно, не правильно. возможно, стоит провести тестирование
Рекс,