Tipo di transazione IsolationLevel dovrebbe essere utilizzato per ignorare inserti ma bloccare la riga selezionata?

StackOverflow https://stackoverflow.com/questions/3404846

Domanda

Ho un processo che avvia una transazione, inserisce un record nella Tabella 1, e poi chiama un servizio Web in esecuzione lunga (fino a 30 secondi). Se la chiamata di servizio Web non riesce quindi l'inserto è rollback (che è quello che vogliamo). Ecco un esempio dell'inserto (in realtà è più inserti in più tabelle, ma sto semplificando per questa domanda):

INSERT INTO Table1 (UserId, StatusTypeId) VALUES (@UserId, 1)

Ho un secondo processo che interroga Table1 dal primo passo in questo modo:

SELECT TOP 1 * FROM Table1 WHERE StatusTypeId=2

e poi aggiorna la fila per un utente. Quando il processo è in esecuzione 1, Tabella 1 è bloccato: processo 2 non sarà completa fino a quando processo 1 finiture, che è un problema perché un lungo ritardo viene introdotto mentre il processo di 1 termina la sua chiamata al servizio Web.

Processo 1 sarà sempre e solo inserire uno StatusTypeId di 1 ed è anche l'unica operazione che inserisce in Tabella 1. Processo 2 sarà solo query StatusTypeId = 2. Voglio dire Processo 2 di ignorare eventuali inserti in Table1 ma bloccare la riga che seleziona. Il livello di isolamento predefinito per processo 2 è in attesa su troppo, ma ho una paura che IsolationLevel.ReadUncommitted permette la lettura dei dati sporchi troppo. Non voglio due utenti in esecuzione di processo 2 e poi accidentalmente ottenere la stessa riga.

C'è un IsolationLevel diverso da utilizzare diverso READUNCOMMITTED che dice ignorano righe inserite, ma assicurarsi che il selezionare le serrature della riga che è selezionata?

È stato utile?

Soluzione

Per quanto riguarda il SELEZIONA bloccata dall'inserto questo dovrebbe essere evitato fornendo indici appropriati.

Tabella di prova.

CREATE TABLE Table1
(
UserId INT PRIMARY KEY,
StatusTypeId INT,
AnotherColumn varchar(50)
)
insert into Table1
SELECT number, (LEN(type)%2)+1, newid()
FROM master.dbo.spt_values
where type='p'

Query finestra uno

BEGIN TRAN
INSERT INTO Table1 (UserId, StatusTypeId) VALUES (5000, 1)
WAITFOR DELAY '00:01';
ROLLBACK

Finestra Query due (Blocchi)

SELECT TOP 1 * 
FROM Table1 
WHERE StatusTypeId=2 
ORDER BY AnotherColumn

Ma se riprovare il test dopo l'aggiunta di un indice non bloccherà CREATE NONCLUSTERED INDEX ix ON Table1 (StatusTypeId,AnotherColumn)

Per quanto riguarda il tuo blocco di righe per Process 2 è possibile utilizzare il seguente (il suggerimento READPAST permetterà 2 transazioni Process 2 concorrenti per iniziare la lavorazione di diversi file piuttosto che uno bloccando l'altro). Si potrebbe trovare questo articolo di Remus Ruşanu rilevanti

BEGIN TRAN

SELECT TOP 1 * 
FROM Table1  WITH (UPDLOCK, READPAST)
WHERE StatusTypeId=2
ORDER BY AnotherColumn

/*
Rest of Process Two's code here
*/
COMMIT

Altri suggerimenti

Modifica: Avendo ri-leggere la domanda, il blocco su qualsiasi insert non deve effettuare qualsiasi select sotto READ COMMITTED questo potrebbe essere un problema con gli indici.

Tuttavia, dai vostri commenti e resto della questione sembra desideri solo una transazione per essere in grado di leggere una riga alla volta, che non è ciò che un livello di isolamento previene.

Impediscono

  • Dirty Read - lettura dei dati non impegnati in una transazione che potrebbe essere il rollback - si verifica in READ UNCOMMITTED, ha impedito a READ COMMITTED, REPEATABLE READ, SERIALIZABLE

  • Non Repeatable Reads - una riga viene aggiornata mentre viene letto in una transazione commit, cioè la stessa lettura di una riga specifica può verificarsi due volte in una transazione e produrre un risultati diversi - si verifica in READ UNCOMMITTED, READ COMMITTED. impedito a REPEATABLE READ, SERIALIZABLE

  • phantom rows - una riga viene inserito o eliminato durante la lettura in una transazione UNCOMMITED, il che significa che la stessa lettura di più righe avvenga due volte in una transazione e produrre risultati diversi, con righe mancanti o aggiunti o - avviene in READ UNCOMMITTED, READ COMMITTED , REPEATABLE READ, impedito nel SERIALIZABLE
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top