De vez en cuando, los administradores de bases de datos SQL Server se tienen desacuerdos con sus contrapartes de desarrollo de aplicaciones – particularmente cuando se trata de algunas de las prácticas de desarrollo Transact SQL (T-SQL) de estos últimos. Una de mis primeras observaciones cuando me uní a mi empleador actual es que casi todos los scripts T-SQL escritos por desarrolladores de aplicaciones usan la sugerencia NOLOCK. De todos modos, de las interacciones que he tenido con estos estimados desarrolladores, no parece que entiendan cómo funciona la sugerencia NOLOCK. Además, aunque parecen estar al tanto de la distinción entre NOLOCK y WITH NOLOCK, tampoco parecen entender cómo los dos difieren uno del otro. En este artículo exploro los detalles internos de la sugerencia NOLOCK y examino las implicaciones de omitir la palabra reservada WITH.
Entendiendo la sugerencia NOLOCK
EL comportamiento por defecto en SQL Server es que cada consulta adquiera su propio bloqueo previo a leer datos desde una tabla dada. Este comportamiento asegura que usted sólo está leyendo datos consolidados. De todos modos, la sugerencia NOLOCK le permite instruir al optimizador de consultas para leer una tabla dada sin obtener un bloqueo exclusivo o compartido. Los beneficios de consultar datos usando la sugerencia NOLOCK es que requiere menos memoria y previene que ocurran bloqueos con otras consultas que puedan estar leyendo datos similares. La única desventaja es que usar la sugerencia NOLOCK puede accidentalmente resultar en la lectura de datos no consolidados “sucios”. En las siguientes secciones, proveeré ejemplos prácticos para usar las sugerencias NOLOCK y WITH NOLOCK.
Para propósitos de esta discusión, usaré a tabla de SQL Server 2016_FIFABallonDOr que contiene a los principales 3 futbolistas nominados para el Balón de Oro de la FIFA en 2016. La vista previa de esta tabla de SQL Server es mostrada en la Tabla 1.
Nominado | Club | Número de camiseta | Votos | Fecha de nacimiento | Lugar de nacimiento | Nacionalidad | Altura |
Antoine Griezmann | Atletico Madrid | 7 | 198 | 21 de Marzo de 1991 | Mâcon | Francesa | 1.75 m |
Lionel Messi | FC Barcelona | 10 | 316 | 24 de Junio de 1987 | Rosario | Argentina | 1.70 m |
Cristiano Ronaldo | Real Madrid | 7 | 745 | 5 de Febrero de 1985 | Funchal | Portugal | 1.85 m |
Ahora asumamos que, habiendo visto el número de camiseta de sus oponentes, Lionel Messi luego decide cambiar su número de camiseta de 10 a 7. Para reflejar este cambio, necesitaríamos correr una sentencia UPDATE contra nuestra tabla de SQL Server. El script UPDATE de muestra que necesitaríamos correr es mostrado en el Script 1.
1 2 3 4 5 |
BEGIN TRANSACTION updateJerseyNr UPDATE A SET [Jersey Number] = 7 FROM [SQLShack].[dbo].[2016_FIFABallonDOr] A WHERE [Nominee] = 'Lionel Messi' |
Usted notará que el Script 1 no tiene un correspondiente COMMIT TRANSACTION updateJerseyNr, lo que significa que los cambios que hemos hecho no han sido consolidados al disco aún. Por tanto, si otro usuario de base de datos fuera a intentar leer el valor del número de camiseta de Lionel Messi como se muestra en la Figura 1, recibiría un mensaje Executing query … sin fin.
Bueno, lo que está pasando aquí es que, como parte de recuperar el número de camiseta de Lionel Messi, el script en la Figura 1 necesita primeramente adquirir un bloqueo compartido contra la tabla 2016_FIFABallonDOr, pero termina teniendo que esperar a que el Script 1 complete sus cambios primero.
Aquí es donde la sugerencia NOLOCK puede ser útil, ya que puede permitir la recuperación del número de camiseta de Lionel Messi sin tener que esperar por ningún bloqueo compartido, como se muestra en Script 2 y Figura 3, respectivamente.
1 2 3 |
SELECT [Jersey Number] FROM [SQLShack].[dbo].[2016_FIFABallonDOr] (NOLOCK) WHERE [Nominee] = 'Lionel Messi' |
De todos modos, los peligros de usar la sugerencia NOLOCK es que si la transacción en Script 1 fuera a ser retrotraída, entonces el valor de la camiseta de Lionel Messi retornaría a 10, lo que significa que si corriera nuevamente el Script 2, usted obtendría un valor diferente del que obtuvo antes.
Beneficios de usar la palabra reservada WITH
En términos de consultar el número de camiseta de Lionel Messi añadiendo la palabra reservada WITH en frente de la sugerencia NOLOCK, usted aún recibiría resultados similares como se muestra en el Script 3 y la Figura 4, respectivamente. De hecho, incluso el plan de ejecución y las estadísticas de TIME/IO del Script 3 aún son similares a los del Script 1.
1 2 3 |
SELECT [Jersey Number] FROM [SQLShack].[dbo].[2016_FIFABallonDOr] WITH (NOLOCK) WHERE [Nominee] = 'Lionel Messi' |
Si la salida de los scripts usando las sugerencias NOLOCK y WITH NOLOCK es idéntica, ¿por qué preocuparse acerca de usar el uno en vez del otro? Bueno, resulta que realmente hay muchas diferencias entre los dos:
1. El soporte para sugerencias sin la palabra reservada WITH pronto será deprecado
Como muestra la documentación de Microsoft en la Figura 5, continuar excluyendo la palabra WITH en una sugerencia significa que usted está básicamente incrementando su deuda técnica, ya que tendrá que volver y refactorizar sus scripts una vez que esta funcionalidad es removida en futuras versiones de SQL Server.
2. Especifique múltiples sugerencias de tabla usando la palabra WITH
Aparte del hecho que los desarrolladores de SQL Server básicamente nos han instruido a usar la palabra WITH cuando especificamos sugerencias de tabla, otro beneficio de usar la palabra WITH es que usted puede incluir múltiples sugerencias de tabla contra la misma tabla, como se muestra en el Script 4.
1 2 3 4 |
SELECT [Jersey Number] FROM [SQLShack].[dbo].[2016_FIFABallonDOr] WITH (TABLOCK, HOLDLOCK) WHERE [Nominee] = 'Cristiano Ronaldo' |
Si usted especifica múltiples sugerencias después de haber omitido la palabra reservada WITH, eso simplemente resultará en el error mostrado en el Script 5 y el Script 6, respectivamente.
1 2 3 4 |
SELECT [Jersey Number] FROM [SQLShack].[dbo].[2016_FIFABallonDOr] (TABLOCK, HOLDLOCK) WHERE [Nominee] = 'Cristiano Ronaldo' |
3. Sin la palabra reservada WITH, usted simplemente tiene un Alias de tabla
En este punto, usted debería ya inclinarse hacia siempre especificar la palabra WITH cuando use sugerencias de tabla, pero sólo para convencerle más, omitir la palabra WITH puede tener consecuencias indeseadas. Si usted olvida incluir NOLOCK en los paréntesis, entonces la sugerencia NOLOCK puede ser confundida con un alias de tabla por el optimizador de consultas, lo que significa que la consulta tendría entonces que esperar por el bloqueo compartido antes de comenzar a leer una tabla dada. Por ejemplo, yo olvidé incluir NOLOCK entre los paréntesis y esto llevó a que la consulta se ejecutara infinitamente mientras que esperaba por el bloqueo compartido.
Conclusión
Hay beneficios y desventajas de especificar la sugerencia NOLOCK, y como resultado, no debería ser simplemente incluida en cada script T-SQL sin un entendimiento claro de lo que hace. A pesar de eso, si toma la decisión de usar la sugerencia de tabla NOLOCK, es recomendado que incluya la palabra reservada WITH.
Vea más
Considere estas herramientas gratis para SQL Server que mejoran la productividad del desarrollador de bases de datos.
Referencias
- ESTBLECER EL NIVEL DE AISLAMIENTO DE TRANSACCIÓN
- LCK_M_X
- Opciones que afectan el Comportamiento del Bloqueo de SQL Server
- Modos de Bloqueo de SQL Server
- Entendiendo el Impacto de las sugerencias NOLOCK y WITH NOLOCK en SQL Server - May 28, 2018
- Cómo reemplazar caracteres especiales ASCII en SQL Server - May 25, 2018
- Convertir resultados de SQL Server a JSON - June 2, 2017