Estou usando o SQL Server 2005 Express.
Em um cenário, adicionei o Begin Transaction
comando imediatamente antes de uma INSERT
instrução em um procedimento armazenado. Quando executei esse procedimento armazenado, ele bloqueou a tabela inteira e todas as conexões simultâneas mostraram uma exibição interrompida até o momento em que isso INSERT
terminou.
Por que a tabela inteira fica bloqueada e como supero esse problema no SQL Server 2005 Express?
Editado
A consulta é como abaixo:
INSERT INTO <table2> SELECT * FROM <table1> WHERE table1.workCompleted = 'NO'
sql-server-2005
RPK
fonte
fonte
Respostas:
Essa resposta pode ser útil para a pergunta original, mas é principalmente para abordar informações imprecisas em outras postagens. Também destaca uma seção de bobagens no BOL.
A seção vinculada da BOL declara:
NB: A partir de 27/08/2014, o BOL foi atualizado para remover as instruções incorretas citadas acima.
Felizmente, este não é o caso. Se assim fosse, as inserções em uma tabela ocorreriam em série e todos os leitores seriam bloqueados de toda a tabela até a transação de inserção ser concluída. Isso tornaria o SQL Server um servidor de banco de dados tão eficiente quanto o NTFS. Não muito.
O senso comum sugere que não pode ser assim, mas como Paul Randall aponta: " Faça um favor a si mesmo, não confie em ninguém ". Se você não pode confiar em ninguém, incluindo o BOL , acho que teremos que provar isso.
Crie um banco de dados e preencha uma tabela fictícia com várias linhas, observando o DatabaseId retornado.
Configure um rastreamento do criador de perfil que rastreie os eventos lock: adquirido e lock: liberado, filtrando o DatabaseId a partir do script anterior, definindo um caminho para o arquivo e observando o TraceId retornado.
Insira uma linha e pare o rastreio:
Abra o arquivo de rastreamento e você deve encontrar o seguinte:
A sequência de bloqueios efetuados é:
Os bloqueios são liberados na ordem inversa. Em nenhum momento um bloqueio exclusivo foi adquirido na mesa.
Sim, ele é. O SQL Server (e possivelmente qualquer mecanismo de banco de dados relacional) não tem previsão de quais outros lotes podem estar em execução ao processar uma instrução e / ou lote, portanto a sequência de aquisição do bloqueio não varia.
Neste exemplo em particular, exatamente os mesmos bloqueios são feitos. Não confie em mim, tente!
fonte
Eu não faço muito trabalho T-SQL, mas lendo a documentação ...
Isso ocorre por design, conforme declarado em BEGIN TRANSACTION :
E, como indicado na documentação do INSERT , ele adquirirá um bloqueio exclusivo na mesa. A única maneira de selecionar um SELECT na tabela é usar
NOLOCK
ou definir o nível de isolamento da transação.fonte