En SQL Server 2008 R2, ¿en qué se diferencian estos dos retrocesos?
- Ejecute una - ALTERdeclaración, durante unos minutos, y luego presione 'Cancelar ejecución'. Tarda unos minutos en retroceder por completo.
- Ejecute la misma - ALTERinstrucción, pero asegúrese de que el- LDFarchivo no sea lo suficientemente grande para que se complete correctamente. Una vez que- LDFse alcanza el límite y no se permite el 'crecimiento automático', la ejecución de la consulta se detiene inmediatamente (o se produce una reversión) con este mensaje de error:
The statement has been terminated.
Msg 9002, Level 17, State 4, Line 1
The transaction log for database 'SampleDB' is full. 
To find out why space in the log cannot be reused, see the 
log_reuse_wait_desc column in sys.databases¿Cómo son estos dos diferentes en los siguientes puntos?
- ¿Por qué es instantáneo el segundo 'retroceso'? No estoy completamente seguro de si podría llamarse una reversión. Supongo que el registro de transacciones se escribe a medida que avanza la ejecución y una vez que se da cuenta de que no hay suficiente espacio para completar la tarea por completo, simplemente se detiene con algún mensaje de "finalización", sin confirmación. 
- ¿Qué sucede cuando la primera reversión toma tanto tiempo (es una reversión de un solo subproceso)? 
 2.1. ¿SQL Server retrocede y deshace las entradas realizadas en el- LDFarchivo?
 2.2. El- LDFtamaño del archivo se reduce al final de la reversión (desde- DBCC SQLPERF(LOGSPACE))
- Una pregunta adicional: durante el segundo escenario, SQL Server comienza a consumir - LDFarchivos con bastante rapidez. En mi caso, aumentó del 18% al 90% en los primeros minutos (<4 minutos). Pero una vez que alcanzó el 99%, permaneció allí durante otros 8 minutos, mientras que el uso fluctuaba entre 99.1% y 99.8%. Sube (99.8%) y baja (99.2%) y sube nuevamente (99.7%) y baja (99.5%) algunas veces antes de que se produzca el error. ¿Qué está pasando detrás de escena?
Se agradece cualquier enlace de MSDN que pueda ayudar a explicar esto más.
A sugerencia de Ali Razeghi, estoy agregando perfmon: Disk Bytes/sec



Respuestas:
Como se indicó anteriormente, después de ejecutar más pruebas, llegué a conclusiones calculadas. Los resumí a todos en una publicación de blog aquí , pero copiaré algún contenido a esta publicación para la posteridad.
Conjetura (basada en algunas pruebas)
A partir de ahora, no tengo una explicación clara de por qué esto es así. Pero a continuación están mis estimaciones basadas en los artefactos reunidos durante las pruebas.
La reversión ocurre en ambos escenarios. Uno es la reversión explícita (el usuario presiona el botón Cancelar), el otro es implícito (el servidor SQL toma esa decisión internamente).
En ambos escenarios, el tráfico que va al archivo de registro es consistente. Vea las imágenes a continuación:
Escenario 1:
Escenario 2:
Un artefacto que reforzó esta línea de pensamiento es capturar Sql Trace durante ambos escenarios.
Comportamiento inexplicable:
Cualquier idea para ayudar a explicar este comportamiento de una mejor manera es bienvenida.
fuente
Intenté el siguiente experimento y obtuve resultados similares. En ambos casos, fn_dblog () muestra una reversión que ocurre y parece suceder más rápido en el Escenario 2 que en el Escenario 1.
Por cierto, coloqué el MDF y el LDF en el mismo disco externo (USB 2.0).
Mi conclusión inicial es que no hay diferencia en la operación de reversión en este caso, y probablemente cualquier diferencia aparente de velocidad esté relacionada con el subsistema de E / S. Esa es solo mi hipótesis de trabajo en este momento.
Escenario 1:
Escenario 2:
Resultados del monitor de rendimiento:
Escenario 1:
Escenario 2:
Código:
USE [maestro]; VAMOS IF DATABASEPROPERTYEX (N'SampleDB ', N'Version')> 0 EMPEZAR ALTER DATABASE [SampleDB] SET SINGLE_USER CON ROLLBACK INMEDIATO; DROP DATABASE [SampleDB]; FINAL; VAMOS CREAR BASE DE DATOS [SampleDB] EN PRIMARIO ( NOMBRE = N'SampleDB ' , FILENAME = N'E: \ data \ SampleDB.mdf ' , TAMAÑO = 3MB , FILEGROWTH = 1MB ) ACCEDER ( NOMBRE = N'SampleDB_log ' , FILENAME = N'E: \ data \ SampleDB_log.ldf ' , TAMAÑO = 1MB , MAXSIZE = 100MB , FILEGROWTH = 4MB ); VAMOS USE [SampleDB]; VAMOS - Agregar una tabla CREAR TABLA dbo.test ( c1 CHAR (8000) NO NULL REPLICATE POR DEFECTO ('a', 8000) ) ENCENDIDO [PRIMARIO]; VAMOS - Asegúrese de que no somos un modelo de recuperación pseudo-simple BACKUP DATABASE SampleDB TO DISK = 'NUL'; VAMOS - Copia de seguridad del archivo de registro REGISTRO DE COPIA DE SEGURIDAD SampleDB TO DISK = 'NUL'; VAMOS - Verifique el espacio de registro utilizado DBCC SQLPERF (ESPACIO DE REGISTRO); VAMOS - ¿Cuántos registros son visibles con fn_dblog ()? SELECCIONAR * DESDE fn_dblog (NULL, NULL); - Alrededor de las 9 en mi caso / ********************************** ESCENARIO 1 ********************************** / - Abra una nueva transacción y luego retírela COMIENZA LA TRANSACCIÓN INSERTAR EN dbo.test VALORES POR DEFECTO; GO 10000 - Let se ejecuta durante 10 segundos y luego presiona cancelar en la ventana de consulta SSMS - Cancelar la transacción - Debería tardar un par de segundos en terminar - No es necesario revertir la transacción, ya que la cancelación ya lo hizo por usted. -- Solo inténtalo. Obtendrás este error - Mensaje 3903, Nivel 16, Estado 1, Línea 1 - La solicitud de TRANSACCIÓN DE ROLLBACK no tiene BEGIN TRANSACTION correspondiente. TRANSACCIÓN EN ROLLBACK; - ¿Cuál es el espacio de registro utilizado? Por encima del 100%. DBCC SQLPERF (ESPACIO DE REGISTRO); VAMOS - ¿Cuántos registros son visibles con fn_dblog ()? SELECCIONE * DE fn_dblog (NULL, NULL); - Alrededor de 91,926 en mi caso - ¿Reserva de registro total mostrada por fn_dblog ()? SELECCIONAR SUMA ([Reserva de registro]) AS [Reserva de registro total] DE fn_dblog (NULL, NULL); - Alrededor de 88.72MB / ********************************** ESCENARIO 2 ********************************** / - Sopla el DB y comienza de nuevo USE [maestro]; VAMOS IF DATABASEPROPERTYEX (N'SampleDB ', N'Version')> 0 EMPEZAR ALTER DATABASE [SampleDB] SET SINGLE_USER CON ROLLBACK INMEDIATO; DROP DATABASE [SampleDB]; FINAL; VAMOS CREAR BASE DE DATOS [SampleDB] EN PRIMARIO ( NOMBRE = N'SampleDB ' , FILENAME = N'E: \ data \ SampleDB.mdf ' , TAMAÑO = 3MB , FILEGROWTH = 1MB ) ACCEDER ( NOMBRE = N'SampleDB_log ' , FILENAME = N'E: \ data \ SampleDB_log.ldf ' , TAMAÑO = 1MB , MAXSIZE = 100MB , FILEGROWTH = 4MB ); VAMOS USE [SampleDB]; VAMOS - Agregar una tabla CREAR TABLA dbo.test ( c1 CHAR (8000) NO NULL REPLICATE POR DEFECTO ('a', 8000) ) ENCENDIDO [PRIMARIO]; VAMOS - Asegúrese de que no somos un modelo de recuperación pseudo-simple BACKUP DATABASE SampleDB TO DISK = 'NUL'; VAMOS - Copia de seguridad del archivo de registro REGISTRO DE COPIA DE SEGURIDAD SampleDB TO DISK = 'NUL'; VAMOS - Ahora, explotemos el archivo de registro dentro de nuestra transacción COMIENZA LA TRANSACCIÓN INSERTAR EN dbo.test VALORES POR DEFECTO; GO 10000 - La reversión nunca se dispara. Intentalo. Obtendrás un error. - Mensaje 3903, Nivel 16, Estado 1, Línea 1 - La solicitud de TRANSACCIÓN DE ROLLBACK no tiene BEGIN TRANSACTION correspondiente. TRANSACCIÓN EN ROLLBACK; - ¿Está el archivo de registro 100% lleno? DBCC SQLPERF (ESPACIO DE REGISTRO); - ¿Cuántos registros son visibles con fn_dblog ()? SELECCIONE * DE fn_dblog (NULL, NULL); - Alrededor de 91,926 en mi caso VAMOS - ¿Reserva de registro total mostrada por fn_dblog ()? SELECCIONAR SUMA ([Reserva de registro]) AS [Reserva de registro total] DE fn_dblog (NULL, NULL); - 88.72MB VAMOSfuente