2009-09-17 15 views
5

Ho un problema di deadlock con due transazioni che non accedono a nessun record comune. Non c'è anche l'escalation del blocco. Quindi non posso spiegare perché è possibile un deadlock.SqlServer 2005: problema di deadlock senza record condivisi

Il deadlock si verifica quando due tali operazioni vengono eseguite contemporaneamente:

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; 

Queste sono le tabelle ei dati per configurare lo scenario:

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) 

Tabella A è nel bel mezzo di tre tavoli. Se cambio qualcosa nella query, ad esempio rimuovi una delle tabelle unite B o C, non esiste un deadlock. Lo stesso quando filtro da A.id anziché da A.value.

Il grafico di deadlock indica che entrambi desiderano impostare un blocco S sull'indice della chiave primaria della tabella A. Ancora: non c'è un'escalation di blocco.

sto usando SqlServer 2005.

  • Perché queste operazioni in conflitto senza alcun accesso ai dati comuni? Qualcuno può spiegarlo?
  • Cosa posso fare per evitarlo? Sto usando NHibernate e non posso cambiare facilmente la query.
  • Potrebbe trattarsi di un problema SqlServer?

Grazie mille.

+0

cosa significa "/ * sincronizzazione transazioni qui * /" significa? –

+0

@Mitch: significa che eseguo la transazione 1 fino a questo punto, quindi eseguo la transazione 2, che attende sulla selezione, quindi eseguo la transazione 1 fino alla fine, che attende anche la selezione. –

risposta

7

Il conflitto potrebbe verificarsi perché SQL Server non si blocca solo a livello di riga, ma anche a livello di pagina o di tabella.

Ciò significa che un record può essere bloccato anche se non è effettivamente in uso, ma solo un altro record "nelle vicinanze".

SQL Server Lock Contention Tamed potrebbe essere utile

+0

Sì: se non è possibile ottenere il blocco a livello di riga, passa a pagina e quindi a tabella. –

+0

Ma non si tratta di un'escalation di blocco? Non dovrebbe essere tracciato nel profiler? –

+0

Dalla mia comprensione, il server Sql potrebbe decidere di utilizzare il blocco della pagina dall'inizio. In quel caso non ci sarebbe stata un'escalation. – Wolfgang

1

Inoltre, un'altra cosa da considerare quando a volte si ottiene questi problemi è che il blocco potrebbe venire da una trasformazione effettuata dai trigger.

+0

Fortunatamente, non ho alcun trigger nel db. Grazie comunque. –

+0

Potresti per favore approfondire perché i trigger fanno la differenza? –

Problemi correlati