¿El aumento de la latencia de la red causará bloqueos de tabla en MS SQL Server?


16

Si estoy haciendo una sola llamada a una base de datos de SQL Server a través de una red de alta latencia, ¿se producirán bloqueos de tabla debido a esa latencia? Digamos que consulto la tabla A para algunos registros, y SQL Server tiene que devolver esos datos a través de una red lenta: ¿habrá un bloqueo de lectura en la tabla A mientras el servidor envía la respuesta a través de la red o SQL Server libera el bloqueo antes de enviarlo? ¿la respuesta?

Además, ¿variaría la respuesta según el tamaño de la respuesta? Si solo tiene que devolver unos pocos KB frente a varios cientos de MB, ¿eso marcaría la diferencia?

Crear una transacción explícita, ejecutar consultas y cerrar la transacción obviamente causaría que las tablas se bloqueen, ya que la duración de la transacción está correlacionada con mi latencia.


A menos que especifique una nolockpista, siempre habrá un bloqueo . La latencia solo determina cuánto tiempo se mantendrá el bloqueo.
Brandon

3
E incluso con nolock, todavía obtendrás cerraduras
billinkc

@brandon ¿Eso está documentado por Microsoft en alguna parte? Mis búsquedas han quedado vacías.
Evan M

1
@Brandon NOLOCK no significa lo que crees que significa.
Aaron Bertrand

3
@Brandon Unless you specify a nolock hint, there will always be a lock.<: esto implica que si usa nolock, es posible que no haya bloqueos. Solo estaba aclarando.
Aaron Bertrand

Respuestas:


15

Si el cliente tarda mucho tiempo en recibir datos y, a su vez, envía un acuse de recibo a SQL Server de que ha recibido los datos que SQL Server tiene que esperar, debido a esta espera, SQL Server no liberará los bloqueos retenidos por la consulta a menos que se reciba un acuse de recibo del cliente.

Esto no es exacto, depende del nivel de aislamiento.

Por defecto, los READ COMMITTEDbloqueos no se mantienen durante la ejecución de las declaraciones. READ COMMITTEDno proporciona consistencia de lectura a nivel de declaración, la única garantía es que no puede leer datos no confirmados. Se adquiere un bloqueo compartido y se mantiene para leer la fila y luego se libera.

A menos que tenga tipos de LOB.

Los tipos de LOB, que son potencialmente muy grandes, no pueden almacenarse en el búfer. Un bloqueo compartido debe ser adquirido y retenido hasta que se complete la declaración, esencialmente dándole REPEATABLE READcomportamiento en READ COMMITTED.

Si estoy haciendo una sola llamada a una base de datos MSSQL a través de una red de alta latencia, ¿se producirán bloqueos de tabla debido a esa latencia?

La latencia no está causando el bloqueo de la mesa, no. Sin embargo, si se ha adquirido un bloqueo de mesa, la latencia lo prolongará.

Para citar a alguien que conoce la mecánica de esto mejor que yo ( @RemusRusanu ):

Los resultados se devuelven al programa cliente a medida que avanza la ejecución. A medida que las filas "burbujean" en el árbol de ejecución, el operador superior generalmente tiene la tarea de escribir estas filas en las memorias intermedias de la red y enviarlas de regreso al cliente. El resultado no se crea primero en algún almacenamiento intermedio (memoria o disco) y luego se devuelve al cliente, sino que se devuelve a medida que se crea (a medida que se ejecuta la consulta). Enviar el resultado al cliente está, por supuesto, sujeto al protocolo de control de flujo de red. Si el cliente no está consumiendo activamente el resultado (por ejemplo, llamando a SqlDataReader.Read ()), entonces el control de flujo tendrá que bloquear el lado emisor (la consulta que se está ejecutando) y esto a su vez suspenderá la ejecución del consulta.[fuente]

Cuando los resultados no se consumen tan rápido como SQL Server puede entregarlos, ya sea debido al cliente o la red, vemos que se ASYNC_NETWORK_IOacumulan las esperas. Para reiterar, esto no influirá en los bloqueos que se adquieren, solo en la duración de su retención.


9

La respuesta de Mark aclaró gran parte de mi confusión, pero quería publicar mis hallazgos después de probar esto usando NetBalancer para emular la latencia.

Hice que mi máquina local llamara a un servidor SQL remoto y ejecutara SELECT e INSERT en una tabla dentro de una pequeña transacción. En la máquina remota, me conecté a la instancia local de SQL y usé un bucle WHILE para iterar repetidamente sobre la tabla sys.dm_tran_locks, buscando cualquier bloqueo en la tabla desde la que estaba modificando y leyendo. Instalé NetBalancer en el servidor y lo usé para emular la latencia de red en la conexión de red del servidor.

Esto es lo que encontré:

  • Para las declaraciones que no devuelven muchos datos al cliente, la latencia no tiene efecto en el bloqueo. Solo estaba devolviendo unos cientos de bytes de datos como máximo. La transacción en mi máquina tenía un WAITFOR de 250 ms que mantuvo los bloqueos, y cuando incrementé la latencia de la red a 5000 ms, la duración del bloqueo se mantuvo cerca de los 250 ms.
  • Para las declaraciones que devuelven muchos datos, la latencia definitivamente afecta el bloqueo . Devolví decenas de miles de filas al cliente, y sin latencia, la duración del bloqueo fue corta. Cuando aumenté la latencia, los bloqueos continuaron hasta que recibí todos los datos.

De esto, concluyo que la latencia no importa siempre que los datos se ajusten al búfer de red. Si SQL tiene que poner muchos datos en el búfer de red, la latencia hará que ese búfer se respalde y SQL retendrá los bloqueos de la tabla hasta que pueda colocar todos los resultados de la consulta en el búfer.


Resultados interesantes ¿Con qué programa / biblioteca cliente es esto?
James L

Buen material. ¿Hay alguna posibilidad de que pueda dedicar un poco más de tiempo a esto y ver si puede determinar el tamaño del resultado en el que esto ocurre?
Mark Storey-Smith

@ MarkStorey-Smith No creo que pueda obtener un valor preciso, y sin duda variaría según la máquina. Desde vircom.com/security/improve-sql-nic-performance , parece que es una configuración en su NIC local, y la del servidor de mi base de datos se configuró en 'auto'
Evan M

@James Acabo de usar SSMS en ambas máquinas
Evan M

0

Si estoy haciendo una sola llamada a una base de datos MSSQL a través de una red de alta latencia, ¿se producirán bloqueos de tabla debido a esa latencia?

Cuando SQL Server ejecuta y completa una consulta, produce los resultados, la coloca en el búfer de salida y la envía al cliente, que luego obtiene el resultado del búfer de salida. SQL Server no liberará los bloqueos retenidos por la consulta a menos que se reciba un acuse de recibo del cliente. Lo que puede causar bloqueo.

Editar: Evan, puede consultar este artículo de soporte de MS

En la sección 3

Bloqueo causado por un SPID cuya aplicación de cliente correspondiente no obtuvo todas las filas de resultados hasta su finalización

Después de enviar una consulta al servidor, todas las aplicaciones deben buscar inmediatamente todas las filas de resultados para completarlas. Si una aplicación no obtiene todas las filas de resultados, se pueden dejar bloqueos en las tablas, bloqueando a otros usuarios. Si está utilizando una aplicación que envía declaraciones SQL de forma transparente al servidor, la aplicación debe buscar todas las filas de resultados. Si no lo hace (y si no se puede configurar para hacerlo), es posible que no pueda resolver el problema de bloqueo. Para evitar el problema, puede restringir las aplicaciones con mal comportamiento a una base de datos de informes o de soporte de decisiones.


Gracias por tu respuesta Shanky! ¿Sabes si esto está documentado en alguna parte?
Evan M


55
Esto no es correcto.
Mark Storey-Smith

Esto es correcto, parece que la aplicación no recupera todas las filas de resultados, se pueden dejar bloqueos en las tablas, bloqueando a otros usuarios. Si está utilizando una aplicación que envía declaraciones SQL de forma transparente al servidor, la aplicación debe buscar todas las filas de resultados. Si no lo hace (y si no se puede configurar para hacerlo), es posible que no pueda resolver el problema de bloqueo. Para evitar el problema, puede restringir las aplicaciones con mal comportamiento a una base de datos de informes o de soporte de decisiones '. Además, estaba hablando en términos generales. Usted puede leer de aquí support2.microsoft.com/kb/224453
Shanky

44
@Shanky Crea una tabla grande. SELECT *desde allí en READ COMMITTEDuna conexión SSMS, supervise las cerraduras de otra. En cualquier momento, ¿cuántas cerraduras ves retenidas?
Mark Storey-Smith
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.