Eu tenho uma tabela T simples que tem Col1, Col2, Col3 e Col4. colunas. Col1 é a chave primária. Agora estou executando algum código simultâneo,
Parallel.For(0, list.Count, new ParallelOptions { MaxDegreeOfParallelism = -1 }, j =>
{
var obj= list[j];
// Do some work
// UPDATE T SET Col2, Col3, Col4 WHERE Col1 =@Col1
Cada valor de col1 é diferente. Mas quando executo este código, estou recebendo muitos deadlocks. Como Col1 é PK (índice clusterizado), agora estou confuso por que isso está acontecendo?
No impasse vitim. Vejo Modo Proprietário: U
Sempre que corro,
USE master
GO
DROP TABLE temp_sp_who2
GO
CREATE TABLE temp_sp_who2 ( SPID INT, Status VARCHAR(1000) NULL, Login SYSNAME NULL, HostName SYSNAME NULL, BlkBy SYSNAME NULL,DBName SYSNAME NULL,Command VARCHAR(1000) NULL, CPUTime INT NULL,DiskIO BIGINT NULL, LastBatch VARCHAR(1000) NULL, ProgramName VARCHAR(1000) NULL,SPID2 INT , RequestId INT NULL )
GO
INSERT INTO temp_sp_who2
EXEC sp_who2
SELECT BlkBy ,count(*) FROM
temp_sp_who2 WHERE CAST(BlkBy AS NVARCHAR(MAX)) <> CAST(SPID AS NVARCHAR(MAX))
GROUP By BlkBy
ORDER BY Count(*) DESC
GO
Vejo que BlkBy é diferente com números altos. Mas BlkBy é sempre alto quando o aplicativo está em execução.
Sem o rastreamento de deadlock, só podemos adivinhar com base nos sintomas.
Bloqueios e deadlocks de longo prazo sugerem que a consulta de atualização de linha singleton está executando uma verificação completa em vez de localizar a linha pelo índice PK. Isso acontecerá se o tipo de dados do parâmetro de chave primária for diferente da coluna referenciada e resultar em uma expressão não sargable que não pode usar o índice PK com eficiência.
A atenção aos detalhes é importante na declaração de parâmetros no código do aplicativo ou no procedimento armazenado para garantir que a definição do parâmetro corresponda ao tipo de coluna referenciado. Uma causa comum de tipos incompatíveis (não necessariamente seus) no ADO.NET é o
AddWithValue
método, que infere o tipo SQL com base no valor fornecido. Strings em .NET são Unicode, portanto, o tipo de parâmetro resultante de um valor de string énvarchar
. A comparação de um parâmetro nvarchar com uma coluna varchar de agrupamento SQL legado impede o uso do índice de chave primária para localizar a linha, resultando em uma verificação completa que leva a bloqueios e impasses no sistema ativo.