No puedo ver ningún alcance de transacción explícito en su código, por lo que no sé qué bloqueos ya están en su lugar cuando está realizando su actualización; Además, no está claro qué nivel de aislamiento está utilizando. Pero el escenario más común en este tipo de situación es que anteriormente en la misma transacción haya emitido una selección (bloqueo de lectura) en las mismas filas que está tratando de actualizar más tarde. Esto provocará una escalada de bloqueo y puede provocar un interbloqueo si dos transacciones intentan hacer lo mismo:
- Transacción A:seleccione con bloqueo de lectura
- Transacción B:seleccionar con readlock
- Transacción A:actualización:quiere escalar su bloqueo de lectura a un bloqueo de escritura, pero tiene que esperar a que la transacción B libere su bloqueo de lectura
- Transacción B:actualización:quiere escalar su bloqueo de lectura a un bloqueo de escritura, pero tiene que esperar a que la transacción A libere su bloqueo de lectura.
¡Bingo! interbloqueo ya que tanto A como B están esperando el uno al otro para liberar sus bloqueos de lectura existentes antes de que puedan hacer su actualización.
Para evitar esto, necesita una pista de updlock en su selección, por ejemplo,
select * from table with (updlock) where blah blah
Esto garantizará que su selección use un bloqueo de escritura en lugar de un bloqueo de lectura, lo que evitará la escalada de bloqueo entre transacciones simultáneas.