Attualmente sto inserendo un record in una tabella di SQL Server e quindi selezionando l'ID di incremento automatico come segue:Perché il seguente SQL Server inserisce deadlock quando viene eseguito all'interno di una transazione?
(@p0 int,@p1 nvarchar(8))INSERT INTO [dbo].[Tag]([Some_Int], [Tag])
VALUES (@p0, @p1)
SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]
(Questo è stato generato utilizzando LINQ to SQL). Per qualche motivo quando eseguo questo codice all'interno di una transazione utilizzando l'oggetto TransactionScope con un livello di isolamento serializzabile, SQL Server genera un errore deadlock. Ho analizzato gli eventi grafico stallo e ha scoperto che i due processi coinvolti sono stati ogni attesa dall'altra per eseguire l'operazione convertito, mi pare di capire le seguenti informazioni:
<resource-list>
<keylock hobtid="72057594101170176" dbid="5" objectname="foo.dbo.Tag" indexname="PK_Tag_1" id="lockb77cdc0" mode="RangeS-S" associatedObjectId="72057594101170176">
<owner-list>
<owner id="processc9be40" mode="RangeS-S"/>
</owner-list>
<waiter-list>
<waiter id="processc9ae38" mode="RangeI-N" requestType="convert"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594101170176" dbid="5" objectname="foo.dbo.Tag" indexname="PK_Tag_1" id="lockb77cdc0" mode="RangeS-S" associatedObjectId="72057594101170176">
<owner-list>
<owner id="processc9ae38" mode="RangeS-S"/>
</owner-list>
<waiter-list>
<waiter id="processc9be40" mode="RangeI-N" requestType="convert"/>
</waiter-list>
</keylock>
</resource-list>
La mia comprensione è che l'ambito della transazione impedirebbe la seconda elaborare dall'esecuzione dell'inserto fino a quando il primo ha terminato sia l'inserimento che la selezione dell'identità. Tuttavia questo non sembra essere il caso. Qualcuno potrebbe far luce sull'approccio migliore per ottenere ciò che richiedo in modo thread-safe?
- Aggiornato -
Basta notare; Sono sicuro al 99% che una connessione non venga condivisa tra i due processi poiché ciascuno crea un nuovo DataContext per comunicare con il database.
- nuovamente aggiornato -
Remo Ruşanu ha sottolineato che alcune informazioni omesse è stato legato al problema, ho cercato di semplificare lo scenario in base al report grafico situazione di stallo, ma ho esteso la spiegazione Qui. Prima di eseguire l'inserimento, eseguo una query esistente sulla tabella in questione per determinare se il tag esiste già. Se lo fa, termino la transazione. In caso contrario, l'inserto dovrebbe andare avanti e quindi eseguirò un aggiornamento, non mostrato qui, su una tabella che ha Some_Int
come chiave primaria, sebbene l'aggiornamento sia puramente per un ultimo valore modificato. Potrebbe anche essere importante che la tabella Tag abbia un indice cluster composto sia dall'ID auto inc sia da Some_Int. Non pensavo che questa ultima informazione fosse rilevante dato che ho provato a cambiare la tabella in modo da avere solo il campo auto inc come la chiave primaria/indice cluster inutilmente.
Grazie.
Una bella domanda! Voglio vedere una risposta. – Chris