Se eu estiver fazendo uma única chamada para um banco de dados SQL Server em uma rede de alta latência, ocorrerão bloqueios de tabela 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 tivesse que retornar apenas alguns KB em vez de várias centenas de MB, isso faria 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 minha latência.
Isso não é preciso, depende do nível de isolamento.
No padrão, os
READ COMMITTED
bloqueios não são mantidos durante a execução das instruções.READ COMMITTED
não fornece consistência de leitura em nível de 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 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, essencialmente dando a você o
REPEATABLE READ
comportamento emREAD COMMITTED
.A latência não está causando o travamento da mesa, não. No entanto, se um bloqueio de tabela foi adquirido, a latência irá prolongá-lo.
Para citar alguém que conhece a mecânica disso melhor do que eu ( @RemusRusanu ):
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
ASYNC_NETWORK_IO
esperas se acumulando. Para reiterar, isso não influenciará os bloqueios adquiridos, apenas a duração em que são mantidos.A resposta de Mark esclareceu muito da minha confusão, mas gostaria de postar minhas descobertas depois de testar isso usando o NetBalancer para emular a latência.
Fiz minha máquina local chamar um servidor SQL remoto e executar 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 na tabela sys.dm_tran_locks, procurando por bloqueios na tabela que estava modificando e lendo. Instalei o NetBalancer no servidor e o usei para emular a latência de rede na conexão de rede do servidor.
Aqui está o que eu encontrei:
A partir disso, estou concluindo que a latência não importa, desde que os dados caibam no buffer de rede. Se o SQL tiver que colocar muitos dados no buffer de rede, a latência fará com que o buffer faça backup e o SQL manterá os bloqueios da tabela até que possa colocar todos os resultados da consulta no buffer.
Quando uma consulta é disparada e concluída pelo SQL Server, ela produz os resultados, coloca-a no buffer de saída e a envia 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 a confirmação seja recebida do cliente. O que pode causar bloqueio.
Editar: Evan, você pode consultar este artigo de suporte do MS
Na seção 3
Bloqueio causado por um SPID cujo aplicativo cliente correspondente não buscou 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 resultado até a conclusão. Se um aplicativo não buscar todas as linhas de resultado, bloqueios podem ser deixados nas tabelas, bloqueando outros usuários. Se você estiver usando um aplicativo que envia instruções SQL de forma transparente ao servidor, o aplicativo deve buscar todas as linhas de resultado. 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 relatório ou banco de dados de suporte à decisão.