Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Deadlock SQL com operações de seleção/atualização em uma tabela


As duas consultas que causam o impasse são o SELECT abaixo (process id="process3980de4558" ):
select @existing = team_it_cube_attr_05 from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key

E a UPDATE consulta abaixo (process id="process386ed48188" ):
UPDATE D
SET D.team_rss_attr_01 = LEFT(S.mkt_prodchar_13,25)...

O <resource-list> seção observa o SELECT query possuía um bloqueio exclusivo (X) em uma página e estava tentando adquirir um bloqueio de intenção compartilhada (IS) em outra página enquanto estava lendo dados. A UPDATE query já possuía um bloqueio IS e estava tentando adquirir um bloqueio X em uma página para realizar a atualização.

Dada a junção contra esta tabela:
...from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key...
...INNER JOIN tbl_Ref_Attr_Prod_Team D ON D.prod_key=P.prod_key...

O SELECT query já possui um bloqueio exclusivo. Isso provavelmente significa que é parte de uma transação maior que já executou um UPDATE em uma consulta prévia. Os bloqueios de consultas anteriores serão mantidos para preservar a integridade dos dados durante a transação (dependendo do nível de isolamento da transação ).

A UPDATE a consulta precisa ler a tabela tbl_Ref_Attr_Prod_team . Ele adquire bloqueios compartilhados por intenção em páginas e linhas durante a leitura de dados. Quando o UPDATE consulta encontrar as linhas correspondentes, ela tentará converter os bloqueios IS em bloqueios X. Os bloqueios IS não são compatíveis com os bloqueios X. Porque o SELECT consulta já tem um bloqueio IS em uma ou mais dessas páginas, as consultas travam entre si.

Uma causa possível seria a falta de índices em tbl_Ref_Attr_Prod_team.prod_key . Sem um índice nesta coluna, o UPDATE consulta verificará todas as linhas na tabela tbl_Ref_Attr_Prod_team .

Mesmo que exista um índice em prod_key , se houver um pequeno número de linhas na tabela, o SQL Server poderá decidir que o desempenho seria melhor se a consulta verificasse a tabela inteira em vez de buscar o índice. Gravar o plano de consulta quando ocorre o deadlock verificaria essa teoria.

Encontramos pequenos bloqueios de tabela regularmente ao preparar novos bancos de dados. Inicialmente, as tabelas são pequenas e as varreduras de tabela causam todos os tipos de deadlocks. Mais tarde, quando as tabelas são maiores, o custo calculado de varredura da tabela excede o custo de busca do índice e os deadlocks não ocorrem mais. Em ambientes de teste onde o número de linhas é sempre pequeno, recorremos ao uso de FORESEEK e WITH INDEX dicas para forçar buscas de índice em vez de varreduras. Estamos ansiosos para poder forçar planos de consulta por meio do recurso de armazenamento de consultas do SQL Server 2016.