ACTUALIZAR tabla de montón -> Puntos muertos en RID

8

Estoy configurando un caso de prueba para probar un cierto escenario de punto muerto y necesito una idea de lo que está sucediendo. Tengo una tabla de montón, llamada convenientemente HeapTable. Esta tabla se actualiza mediante 2 transacciones de manera simulada.

Transacción 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

Transacción 2:

BEGIN TRAN

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

ROLLBACK TRAN

Primero disparo la transacción 1, seguida de cerca por la transacción 2. Como se esperaba, la transacción 1 reclamará algunos bloqueos exclusivos, junto con algunos intentos exclusivos. La transacción 2 entrará y solicitará un bloqueo de actualización en el mismo 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

Me sorprendió ver que la segunda transacción solicita un bloqueo de actualización en el mismo RID, ya que pensé que esto apuntaba a un solo registro y ambas declaraciones de actualización manejan datos diferentes. De alguna manera esperaba un conflicto a nivel de página.

Cuando la segunda actualización de la transacción 1 se inicia en la transacción 2 se verá como una víctima de punto muerto que dará como resultado una reversión de la transacción 2 y la finalización de la transacción 1.

¿Alguien puede explicarme por qué la segunda transacción requeriría un bloqueo de actualización en el mismo RID a pesar de actualizar un registro diferente?

Sé cómo solucionar esto (por ejemplo, con un índice). No estoy buscando una solución, en realidad estoy buscando una explicación de por qué 2 actualizaciones que manejan diferentes registros en un montón querrían bloquear el mismo RID. Estoy usando el aislamiento de lectura comprometida. No hay índices no agrupados en la tabla.

Jens
fuente

Respuestas:

18

Sin un índice FirstNameactivado, SQL Server tiene que verificar cada fila para ver si califica para el UPDATE.

Se necesita un Ubloqueo de actualización al leer cada fila para evitar un escenario de bloqueo común. Podría tomar un Sbloqueo compartido , pero aún así estaría bloqueado por el Xbloqueo exclusivo que mantiene la primera transacción.

Paul White 9
fuente