SqlServer 2005: problema deadlock senza record condivisi
-
08-07-2019 - |
Domanda
Ho un problema di deadlock con due transazioni che non accedono ad alcun record comune. Non esiste inoltre alcuna escalation di blocco. Quindi non posso spiegare perché sia ??possibile un deadlock.
Il deadlock si verifica quando due di queste transazioni 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 e i dati per impostare 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
è al centro di tre tabelle. Se cambio qualcosa nella query, ad esempio rimuovo una delle tabelle unite B
o C
, non c'è deadlock. Lo stesso quando filtro per A.id
anziché A.value
.
Il deadlock-graph mi dice che entrambi vogliono impostare un blocco S sull'indice della chiave primaria della tabella A
. Ancora una volta: non c'è escalation di blocco.
Sto usando SqlServer 2005.
- Perché queste transazioni sono in conflitto senza accedere a dati comuni? Qualcuno può spiegare questo?
- Cosa posso fare per evitarlo? Sto usando NHibernate e non posso cambiare la query così facilmente.
- Potrebbe essere un problema SqlServer?
Grazie mille.
Soluzione
Il conflitto potrebbe verificarsi perché SQL Server non blocca solo a livello di riga, ma anche a livello di pagina o persino di tabella.
Ciò significa che un record può essere bloccato anche se in realtà non è in uso, ma solo un record diverso "vicino".
Contesa di blocco di SQL Server domata potrebbe essere utile
Altri suggerimenti
Inoltre, un'altra cosa da considerare quando si verificano a volte questi problemi è che il blocco potrebbe provenire dall'elaborazione eseguita dai trigger.