A latência aumentada da rede causará bloqueios de tabela no MS SQL Server?

16

Se eu estiver fazendo uma única chamada para um banco de dados do SQL Server em uma rede de alta latência, os bloqueios de tabela ocorrerão devido a essa latência? Digamos que eu consulte a tabela A para alguns registros e o SQL Server precise retornar esses dados em uma rede lenta - haverá um bloqueio de leitura na tabela A enquanto o servidor envia a resposta pela rede ou o SQL Server libera o bloqueio antes de enviar a resposta?

Além disso, a resposta varia com base no tamanho da resposta? Se ele apenas devolver algumas KB vs várias centenas de MB, isso faria alguma diferença?

Criar uma transação explícita, executar consultas e fechar a transação obviamente causaria o bloqueio das tabelas, pois a duração da transação está correlacionada com a minha latência.

Evan M
fonte
A menos que você especifique uma nolockdica, sempre haverá um bloqueio . A latência apenas determina quanto tempo o bloqueio será mantido.
Brandon
3
E mesmo com nolock, você ainda terá bloqueios
billinkc 30/09/14
@brandon Isso está documentado pela Microsoft em algum lugar? Minhas pesquisas ficaram vazias.
Evan H
11
@Brandon NOLOCK não significa o que você pensa que significa.
Aaron Bertrand
3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- isso implica que, se você usar o nolock, talvez não haja bloqueios. Eu estava apenas esclarecendo.
Aaron Bertrand

Respostas:

15

Se o cliente demorar muito tempo para receber dados e, por sua vez, enviar ao SQL Server a confirmação de que recebeu os dados que o SQL Server precisa aguardar, devido a essa espera, o SQL Server não liberará os bloqueios retidos pela consulta, a menos que seja recebida uma confirmação do cliente.

Isso não é exato, depende do nível de isolamento.

Nos READ COMMITTEDbloqueios padrão, não são mantidos durante a execução das instruções. READ COMMITTEDnão fornece consistência de leitura no nível da instrução, a única garantia é que você não pode ler dados não confirmados. Um bloqueio compartilhado é adquirido e mantido para ler a linha e, em seguida, liberado.

A menos que você tenha tipos de LOB.

Os tipos de LOB, sendo potencialmente muito grandes, não podem ser armazenados em buffer. Um bloqueio compartilhado deve ser adquirido e mantido até que a instrução seja concluída, fornecendo essencialmente um REPEATABLE READcomportamento em READ COMMITTED.

Se eu estiver fazendo uma única chamada para um banco de dados MSSQL em uma rede de alta latência, os bloqueios de tabela ocorrerão devido a essa latência?

A latência não está causando o bloqueio da tabela, não. No entanto, se um bloqueio de tabela foi adquirido, a latência vai prolongá-lo.

Para citar alguém que conhece a mecânica disso melhor do que eu ( @RemusRusanu ):

Os resultados são retornados ao programa cliente à medida que a execução prossegue. À medida que as linhas "borbulham" na árvore de execução, o operador principal geralmente é encarregado de gravar essas linhas nos buffers de rede e enviá-las de volta ao cliente. O resultado não é criado primeiro em algum armazenamento intermediário (memória ou disco) e depois enviado de volta ao cliente; em vez disso, é devolvido conforme está sendo criado (à medida que a consulta é executada). O envio do resultado de volta ao cliente está, obviamente, sujeito ao protocolo de controle de fluxo de rede. Se o cliente não estiver consumindo ativamente o resultado (por exemplo, chamando SqlDataReader.Read ()), eventualmente o controle de fluxo precisará bloquear o lado de envio (a consulta que está sendo executada) e, por sua vez, suspenderá a execução do inquerir.[fonte]

Onde os resultados não são consumidos tão rapidamente quanto o SQL Server pode entregá-los, seja devido ao cliente ou à rede, vemos as ASYNC_NETWORK_IOesperas se acumulando. Para reiterar, isso não influenciará os bloqueios adquiridos, apenas a duração em que eles são mantidos.

Mark Storey-Smith
fonte
9

A resposta de Mark esclareceu muita confusão, mas eu queria postar minhas descobertas depois de testar isso usando o NetBalancer para emular a latência.

Minha máquina local chamou um servidor SQL remoto e executou SELECTs e INSERTs em uma tabela dentro de uma pequena transação. Na máquina remota, conectei-me à instância SQL local e usei um loop WHILE para iterar repetidamente sobre a tabela sys.dm_tran_locks, procurando por bloqueios na tabela que eu estava modificando e lendo. Instalei o NetBalancer no servidor e o usei para emular a latência da rede na conexão de rede do servidor.

Aqui está o que eu encontrei:

  • Para instruções que não retornam muitos dados para o cliente, a latência não afeta o bloqueio. Eu estava retornando apenas algumas centenas de bytes de dados, no máximo. A transação na minha máquina tinha um WAITFOR de 250ms que mantinha os bloqueios e, quando eu aumentava a latência da rede para 5000ms, a duração do bloqueio ficava perto de 250ms.
  • Para instruções que retornam muitos dados, a latência definitivamente afeta o bloqueio . Voltei dezenas de milhares de linhas ao cliente e, sem latência, a duração do bloqueio foi curta. Quando aumentei a latência, os bloqueios continuaram até que eu recebi todos os dados.

A partir disso, concluo que a latência não importa, desde que os dados caibam no buffer da rede. Se o SQL precisar colocar muitos dados no buffer de rede, a latência fará o backup desse buffer e o SQL manterá os bloqueios da tabela até que ele possa colocar todo o resultado da consulta no buffer.

Evan M
fonte
Resultados interessantes. Com qual programa / biblioteca cliente está?
James L
Coisa boa. Alguma chance de você gastar um pouco mais de tempo nisso e ver se consegue determinar o tamanho do resultado em que isso ocorre?
Mark-Storey-Smith
@ MarkStorey-Smith Acho que não consigo obter um valor preciso, e sem dúvida varia de acordo com a máquina. Em vircom.com/security/improve-sql-nic-performance , parece que é uma configuração na NIC local e a do meu servidor de banco de dados foi definida como 'auto'
Evan M
@ James Eu só SSMS usado em ambas as máquinas
Evan M
0

Se eu estiver fazendo uma única chamada para um banco de dados MSSQL em uma rede de alta latência, os bloqueios de tabela ocorrerão devido a essa latência?

Quando uma consulta é disparada e concluída pelo SQL Server, ela produz os resultados, coloca-a no buffer de saída e envia-a ao cliente, que busca o resultado no buffer de Saída. O SQL Server não liberará os bloqueios mantidos pela consulta, a menos que seja recebida uma confirmação do cliente. O que pode causar o bloqueio.

Edit: Evan, você pode consultar este artigo de suporte da MS

Na seção 3

Bloqueio causado por um SPID cujo aplicativo cliente correspondente não obteve todas as linhas de resultado até a conclusão

Depois de enviar uma consulta ao servidor, todos os aplicativos devem buscar imediatamente todas as linhas de resultados até a conclusão. Se um aplicativo não buscar todas as linhas de resultado, os bloqueios poderão ser deixados nas tabelas, bloqueando outros usuários. Se você estiver usando um aplicativo que envie transparentemente instruções SQL para o servidor, o aplicativo deverá buscar todas as linhas de resultados. Caso contrário (e se não puder ser configurado para isso), talvez você não consiga resolver o problema de bloqueio. Para evitar o problema, você pode restringir aplicativos mal comportados a um banco de dados de relatórios ou de suporte à decisão.

Shanky
fonte
Obrigado pela sua resposta Shanky! Você sabe se isso está documentado em algum lugar?
Evan M
5
Isso não está correto.
Mark-Storey-Smith
Está correto, parece que 'o aplicativo não busca todas as linhas de resultado, os bloqueios podem ser deixados nas tabelas, bloqueando outros usuários. Se você estiver usando um aplicativo que envie transparentemente instruções SQL para o servidor, o aplicativo deverá buscar todas as linhas de resultados. Caso contrário (e se não puder ser configurado para isso), talvez você não consiga resolver o problema de bloqueio. Para evitar o problema, você pode restringir aplicativos mal comportados a um banco de dados de relatórios ou de suporte à decisão. ' Mais do que eu estava falando em termos gerais. Você pode ler a partir daqui support2.microsoft.com/kb/224453
shanky
4
@ Shanky Crie uma tabela grande. SELECT *dele em READ COMMITTEDuma conexão SSMS, o monitor bloqueia a partir de outra. A qualquer momento, quantos bloqueios você vê retidos?
Mark-Storey-Smith