declarações SQL Server Select causando o bloqueio
-
06-07-2019 - |
Pergunta
Estamos usando um banco de dados SQL Server 2005 (sem versão de linha) com uma enorme declaração de seleção, e estamos vendo isso bloquear outras declarações de correr (visto usando sp_who2
). Eu não sabia que instruções SELECT podem causar o bloqueio -? Não há nada que eu possa fazer para mitigar este
Solução
SELECIONAR pode bloquear atualizações. Um modelo de dados projetado corretamente e consulta só irá causar bloqueio mínima e não ser um problema. O 'normal' com sugestão NOLOCK é quase sempre a resposta errada. A resposta adequada é ajustar sua consulta para que ele faz enormes mesas não digitalização.
Se a consulta for untunable então você deve primeiro considerar nível de isolamento de instantâneo , segundo você deve considerar o uso banco de dados e última opção deve ser DIRTY LÊ (e é melhor para mudar a nível de isolamento em vez de usar a dica NOLOCK). Note-se que leituras sujas, como o nome indica claramente, retornará dados inconsistentes (por exemplo. A folha total pode ser desequilibrado).
Outras dicas
A partir documentação :
fechaduras
Shared (S)
permitir transações concorrentes para ler(SELECT)
um recurso sob controle de simultaneidade pessimista. Para mais informações, consulteTypes of Concurrency Control
. Sem outras transações pode modificar os dados enquanto existem bloqueiosshared (S)
no recurso. fechadurasShared (S)
sobre um recurso são liberados tão logo os concluída operação de leitura, a menos que o nível de isolamento transação está definido para leitura repetida ou superior, ou uma dica de bloqueio é usado para manter os bloqueiosshared (S)
para a duração da transação.
A shared lock
é compatível com outro bloqueio compartilhado ou um bloqueio de atualização, mas não com um bloqueio exlusive.
Isso significa que suas consultas SELECT
irão bloquear UPDATE
e INSERT
consultas e vice-versa.
A SELECT
consulta irá colocar um bloqueio compartilhado temporária quando se lê um bloco de valores da tabela, e removê-lo quando terminar de ler.
Para o tempo existe o bloqueio, você não será capaz de fazer qualquer coisa com os dados na área bloqueada.
Duas consultas SELECT
nunca vai bloquear uns aos outros (a menos que sejam SELECT FOR UPDATE
)
Você pode ativar o nível de isolamento SNAPSHOT
em seu banco de dados e usá-lo, mas nota que isso não impedirá consultas UPDATE
que está sendo bloqueado por consultas SELECT
(que parece ser o seu caso).
Ele, porém, impedirá consultas SELECT
de ser bloqueado por UPDATE
.
Observe também que SQL Server
, Oracle
ao contrário, usos bloquear gerente e mantém encaixar em uma lista na memória associada.
Isso significa que sob carga pesada, o simples fato de colocar e retirar o bloqueio pode ser lenta, uma vez que a lista ligada em si deve ser bloqueado pelo segmento transação.
Para executar sujo lê você pode:
using (new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions {
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
//Your code here
}
ou
SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."
lembre-se que você tem que escrever WITH (NOLOCK) depois de cada tabela que deseja leitura suja
Você pode definir o nível de transação a leitura não consolidada
Você também pode obter impasses:
"impasses envolvendo apenas uma tabela" http: // sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx
e ou resultados incorretos:
"Seleciona sob READ COMMITTED e REPEATABLE READ pode retornar resultados incorretos."
Você pode usar dica de tabela WITH(READPAST)
. É diferente do que a WITH(NOLOCK)
. Ele irá obter os dados antes que a transação foi iniciada e não irá bloquear ninguém. Imagine que, você executou a declaração antes que a transação foi iniciada.
SELECT * FROM table1 WITH (READPAST)