¿Desconectar la red detiene una consulta?

13

Recientemente ejecuté una consulta de actualización contra 100,000 registros. Me di cuenta de que había cometido un error mientras se ejecutaba la consulta y desconecté rápidamente el cable de red.

¿La consulta de actualización

  1. dejar de procesar y deshacer por completo?
  2. continuar procesando hasta completar y comprometerse?
  3. ¿dejar de procesar y dejar solo parte de las filas de destino actualizadas?
robocop
fuente
2
una vez que una consulta llegue al servidor, continuará a menos que cancele la consulta en el servidor.
JP Chauhan
1
El comentario de Martin proporciona la respuesta directa a su pregunta, robocop. Si la red notifica a SQL Server de la desconexión antes de que su consulta termine de ejecutarse, SQL Server la revertirá. De lo contrario, si la consulta se completa antes de que se indique a SQL Server que hubo una desconexión de la red, se confirmará. En ningún caso (suponiendo que haya escrito una sola consulta de actualización) SQL Server ejecutará una actualización parcial.
Nick Chammas el

Respuestas:

22

Como lo mencionaron Nick y Martin, el estado eventual de su consulta depende de si SQL Server conoce la extracción de cable de su red antes de que se complete la consulta. De Books Online (aunque me parece interesante que haya temas equivalentes para esto en 2000 , 2005 , 2008 y 2008 R2 , pero no en 2012 o 2014):

Si un error impide la finalización exitosa de una transacción, SQL Server revierte automáticamente la transacción y libera todos los recursos que posee. Si la conexión de red del cliente a una instancia del Motor de base de datos se interrumpe, cualquier transacción pendiente para la conexión se revierte cuando la red notifica a la instancia del corte. Si la aplicación del cliente falla o si la computadora del cliente se cae o se reinicia, esto también interrumpe la conexión, y la instancia del Motor de base de datos revierte las conexiones pendientes cuando la red lo notifica. Si el cliente cierra la sesión de la aplicación, las transacciones pendientes se revierten.

(Por otro lado, las conexiones de palabras en la 2da última oración probablemente fueron transacciones . No sé cómo se deshace una conexión).

De manera similar, SQL Server puede deshacer o rehacer transacciones durante la recuperación después de que el servidor se cierre inesperadamente, y esto dependerá del estado de la transacción en el momento del cierre. He visto a personas usar esta táctica para lograr lo que estaba tratando de hacer (cancelar las transacciones) y cuando el servidor se inició nuevamente, gran parte del trabajo fue simplemente rehecho (por lo que el efecto neto de su reacción instintiva estuvo mucho más cerca a cero de lo que esperaban).

Entonces, en lugar de estar sujeto a esto, en lugar de hacer cosas drásticas en pánico, como tirar de un cable de red o apagar la máquina, sugiero que en el futuro tenga una mejor disciplina sobre la ejecución de consultas ad hoc contra sistemas importantes. Por ejemplo, en lugar de:

UPDATE dbo.sometable 
-- where *oops* I forgot this part

Tengo esto:

BEGIN TRANSACTION;

UPDATE dbo.sometable
-- where *oops* I forgot this part

-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;

Luego, si la actualización fue correcta, puede resaltar la COMMITparte y ejecutarla. Si no fuera así, puede resaltar con calma la ROLLBACKparte y ejecutarla. Incluso puede usar complementos como SSMS Tools Pack para editar su New Queryplantilla para incluir esa plantilla.

Ahora aún podría meterte en problemas en caso de que ejecutes la consulta y luego no confirmes ni reviertas, porque ahora tu transacción está bloqueando a otros usuarios. Pero esto es mejor que modificar irrevocablemente los datos.

Y, por supuesto, como siempre, tenga una copia de seguridad en la que pueda confiar.

Aaron Bertrand
fuente
55
Este es un excelente consejo y aborda la raíz del problema del OP, pero en realidad no responde a la pregunta de si la consulta continuó ejecutándose o no.
Nick Chammas
3
Gracias @Nick, mi motivación fue abordar la causa (que estimuló la pregunta), no el síntoma, pero he actualizado mi respuesta.
Aaron Bertrand
8

@ Aaron es correcto. Crear una transacción antes de tus comandos es tu mejor opción. Si no puede recordar hacer eso, entonces una opción es ir a la Tools-Optionsconfiguración y encender SET IMPLICIT_TRANSACTIONS. Esto iniciará automáticamente una transacción tan pronto como se ejecuten ciertos comandos. Esto incluye UPDATE, DELETEetc. Esto parece ser una lista bastante completa de cualquier comando que haría "change"algo. SELECTtambién se incluye en la lista y willcomienza una transacción. Puede ver una lista completa de los comandos que inician una transacción con esta configuración aquí . No creará una transacción si ya se ha iniciado una. Ahora el lado negativo de esto es que tendrá que recordar COMMITdespués de cualquier cambio realizado.

NOTA: Según la sugerencia de @ Aaron, voy a volver a enfatizar esto.

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

Básicamente, estás intercambiando el olvido de BEGINuna transacción y arruinando algo, por olvidar COMMITuna transacción y colgarla si la dejas abierta y luego te vas por el día. Probé simplemente cerrando una ventana de consulta pensando que revertiría mi transacción, sin embargo, me preguntó si quería confirmar o revertir la transacción.

ingrese la descripción de la imagen aquí

Kenneth Fisher
fuente
En realidad: SELECT se iniciará una transacción (que también se documenta en el enlace informados)
a_horse_with_no_name
¡Gracias @a_horse_with_no_name por atrapar eso! No leí con suficiente atención y estaba perdiendo memoria (eso obviamente estaba mal)
Kenneth Fisher
1
Esta es una publicación útil, pero en realidad no responde a la pregunta del OP sobre si la consulta continuó ejecutándose o no.
Nick Chammas
2
Fue un complemento de la respuesta de @ Aaron. Fue demasiado para poner un comentario.
Kenneth Fisher
2

Creo que realmente depende:

Si el comando ya llega al servidor antes de desconectar el cable de red, el comando continuará ejecutándose normalmente.

Si tiene un TransactionScope (utilizado en .Net, no estoy seguro de otros idiomas) para encapsular todos los comandos de actualización, probablemente pueda detener la transacción para que se confirme solo si no se ha ejecutado la transacción. .

Rex
fuente
2
Dijiste "si el comando ya llega al servidor antes de desconectar el cable de red, el comando continuará ejecutándose normalmente". Esto se contradice con la página BOL de SQL Server que Martin ha vinculado anteriormente. Consulte "Errores durante el procesamiento de la transacción" .
Nick Chammas
tienes razón. Con una transacción especificada, el comando se revertirá automáticamente. pero como experimentamos, cuando no se especificó ninguna transacción explícitamente, el comando (una actualización por lotes sin una transacción) se ejecutó por completo, incluso detuvimos nuestra aplicación en el medio, lo que realmente interrumpió la conexión, pero en realidad no es un buen ejemplo como el momento Probablemente no era correcto. probablemente sea bueno hacer algunas pruebas para eso
Rex