È possibile utilizzare LOCK per rendere le cose SERIALIZZABILI ma ciò riduce la concorrenza. Perché non provare prima la condizione comune ("principalmente inserire o selezionare per lo più") seguita da una gestione sicura dell'azione "correttiva"? Cioè, il pattern "JFDI" ...
Per lo più INSERT attesi (Ball Park 70-80% +):
Basta provare a inserire. Se fallisce, la riga è già stata creata. Non c'è bisogno di preoccuparsi della concorrenza perché TRY/CATCH si occupa di duplicati per te.
BEGIN TRY
INSERT Table VALUES (@Value)
SELECT @id = SCOPEIDENTITY()
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE -- only error was a dupe insert so must already have a row to select
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
Per lo più scegliere il:
simili, ma cercare di ottenere i dati prima. Nessun dato = INSERT necessario. Anche in questo caso, se 2 chiamate simultanee tentano di INSERIRE perché entrambi hanno trovato la riga mancante degli handle TRY/CATCH.
BEGIN TRY
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
IF @@ROWCOUNT = 0
BEGIN
INSERT Table VALUES (@Value)
SELECT @id = SCOPEIDENTITY()
END
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
Il 2 ° sembra ripetersi, ma è altamente concomitante. Serrature sarebbero ottenere lo stesso, ma a scapito di concorrenza ...
Edit:
Perché non usare MERGE ...
se si utilizza la clausola OUTPUT sarà solo ritorno cosa viene aggiornato. Quindi è necessario un dummy UPDATE per generare la tabella INSERTED per la clausola OUTPUT. Se si devono eseguire aggiornamenti fittizi con molte chiamate (come implicito dall'OP), molte scritture dei registri devono essere solo per poter utilizzare MERGE.
Questo è simile a: http://stackoverflow.com/questions/13540/insert-update-stored-proc-on-sql-server/193876#193876 –
Sono d'accordo è simile, ma direi che la differenza è che non è necessario un aggiornamento, solo un inserimento o una selezione.Nella tua risposta, usi SERIALIZABLE come suggerimento congiunto. Potrebbe essere la tua raccomandazione per la query sopra sulla dichiarazione SELECT? – 8kb
Appare un inserto con l'hint serializzabile, potenzialmente in una transazione dovrebbe fare il trucco. Posso provare a scrivere una risposta ma questo iPad mi fa sembrare sfacciato :( –