2009-09-17 10 views
5

Tengo un problema de interbloqueo con dos transacciones que no tienen acceso a ningún registro común. Tampoco hay escalada de bloqueo. Entonces no puedo explicar por qué es posible un punto muerto.SqlServer 2005: problema de interbloqueo sin registros compartidos

El interbloqueo se produce cuando dos de tales transacciones se ejecutan al mismo tiempo:

begin transaction 

update A set [value] = [value] 
where id = 1; /* resp. 2 */ 

/* synchronize transactions here */ 

SELECT * 
FROM 
A inner join B on A.B_FK = B.id 
inner join C on C.A_FK = A.id 
WHERE 
A.[value] = 1; /* resp. 2 */ 

rollback; 

Estas son las tablas y los datos para configurar el escenario:

CREATE TABLE A (
    id INT NOT NULL, 
    [value] INT, 
    B_FK INT 
    primary key (id) 
) 

CREATE TABLE B (
    id INT NOT NULL, 
    primary key (id) 
) 

CREATE TABLE C (
    id INT NOT NULL, 
    A_FK INT 
    primary key (id) 
) 

INSERT INTO A VALUES(1, 1, 1) 
INSERT INTO B VALUES(1) 
INSERT INTO C VALUES(1, 1) 

INSERT INTO A VALUES(2, 2, 2) 
INSERT INTO B VALUES(2) 
INSERT INTO C VALUES(2, 2) 

Tabla A está en el medio de tres tablas Si cambio algo en la consulta, por ejemplo, elimine una de las tablas unidas B o C, no hay interbloqueo. Lo mismo cuando filtro por A.id en lugar de A.value.

El gráfico de interbloqueo me dice que ambos desean establecer un bloqueo S en el índice de clave principal de la tabla A. De nuevo: no hay escalada de bloqueo.

estoy usando SqlServer 2005.

  • ¿Por qué son estas transacciones en conflicto sin tener acceso a los datos comunes? ¿Alguien puede explicar esto?
  • ¿Qué puedo hacer para evitarlo? Estoy usando NHibernate y no puedo cambiar la consulta tan fácilmente.
  • ¿Podría ser un problema SqlServer?

Muchas gracias.

+0

¿Qué significa "/ * sincronizar las transacciones aquí * /"? –

+0

@Mitch: Significa que ejecuto la transacción 1 hasta este punto, luego ejecuto la transacción 2, que espera en la selección, luego ejecuto la transacción 1 hasta el final, que también espera en la selección. –

Respuesta

7

El conflicto podría ocurrir, porque SQL-Server no se bloquea solo en el nivel de la fila, sino también en la página o incluso en el nivel de la tabla.

Eso significa que un registro se puede bloquear aunque no esté realmente en uso, pero solo un registro diferente "cercano".

SQL Server Lock Contention Tamed podría ser útil

+0

Sí, si no puede obtener el bloqueo a nivel de fila, escala a la página y luego a la tabla. –

+0

¿Pero no es esto una escalada de bloqueo? ¿No debería rastrearse en el generador de perfiles? –

+0

Según entiendo, Servidor SQL podría decidir utilizar el bloqueo de página desde el principio. En ese caso no habría escalada. – Wolfgang

1

También, otra cosa a tener en cuenta al que a veces encuentras estos problemas es que el bloqueo podría provenir de procesamiento realizado por los disparadores.

+0

Afortunadamente, no tengo ningún activador en el db. Gracias de cualquier manera. –

+0

¿Podría explicar por qué los factores desencadenantes hacen alguna diferencia? –

Cuestiones relacionadas