Tabela heap UPDATE -> Deadlocks no RID

8

Estou configurando um caso de teste para provar um determinado cenário de conflito e exigir algumas dicas sobre o que está acontecendo. Eu tenho uma tabela de pilha, conventientemente chamada HeapTable. Esta tabela é atualizada por 2 transações simultaneamente.

Transação 1:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Dylan'
WHERE FirstName = 'Ovidiu';

WAITFOR DELAY '00:00:15';

UPDATE HeapTable
SET FirstName = 'Bob'
WHERE FirstName = 'Thierry';

ROLLBACK TRANSACTION

Transação 2:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';

ROLLBACK TRAN

Eu aciono a transação 1 primeiro, seguida de perto pela transação 2. Como a transação esperada 1 reivindicará alguns bloqueios exclusivos, juntamente com outros de intenção. A transação 2 entrará e solicitará um bloqueio de atualização no mesmo RID:

spid dbid   ObjId       IndId   Type    Resource     Mode   Status
55    5     711673583   0       RID     1:24336:10   X      GRANT
57    5     711673583   0       RID     1:24336:10   U      WAIT

Fiquei meio surpreso ao ver a segunda transação solicitar um bloqueio de atualização no mesmo RID, pois achei que isso apontava para um único registro e as duas instruções de atualização lidam com dados diferentes. De alguma forma, eu esperava um conflito no nível da página.

Quando a segunda atualização da transação 1 iniciar a transação 2 será vista como vítima de impasse, resultando em uma reversão da transação 2 e na conclusão da transação 1.

Alguém pode me explicar por que a segunda transação exigiria um bloqueio de atualização no mesmo RID, embora a atualização de um registro diferente?

Eu sei como consertar isso (por exemplo, com um índice). Não estou procurando uma correção, na verdade, estou procurando uma explicação sobre por que 2 Atualizações que manipulam registros diferentes em um heap desejam bloquear o mesmo RID. Estou usando o isolamento confirmado por leitura. Não há índices não clusterizados na tabela.

Jens
fonte

Respostas:

18

Sem um índice ativado FirstName, o SQL Server precisa verificar todas as linhas para verificar se está qualificado para o UPDATE.

É necessário um Ubloqueio de atualização ao ler cada linha para evitar um cenário de conflito comum. Pode levar um Sbloqueio compartilhado , mas isso ainda será bloqueado pelo Xbloqueio exclusivo mantido pela primeira transação.

Paul White 9
fonte