Blocca CREA TABELLA


19

In un'altra applicazione sono stato colpito da una cattiva progettazione: più thread eseguono un EnsureDatabaseSchemaExists()metodo contemporaneamente, che assomiglia sostanzialmente a questo:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'MyTable') AND type = N'U') BEGIN

    CREATE TABLE MyTable ( ... );

END

Tuttavia, anche se eseguito in una transazione SERIALIZZABILE, questo codice non sembra essere thread-safe (ovvero il codice parallelo tenta di creare la tabella più volte). C'è qualche possibilità di forzare l'istruzione SELECT ad acquisire un blocco che impedisce a un altro thread di fare la stessa istruzione SELECT?

Esiste un modello migliore per i metodi multi-threaded-SecureSchemaExists ()?

Risposte:


18

La soluzione migliore è utilizzare una transazione contenente esplicito e acquisire un blocco esclusivo personalizzato per proteggere l'intera operazione ( SELECTe CREATE TABLE) utilizzando sp_getapplock . Gli oggetti di sistema non rispettano le richieste a livello di isolamento e utilizzano i blocchi allo stesso modo delle tabelle utente, in base alla progettazione.

La condizione di competizione nel codice originale è che più thread possono concludere che la tabella non esiste prima che qualsiasi thread arrivi fino CREATE TABLEall'istruzione.


6
+1 assicurati solo che l'applock comprenda il controllo SELECT . Altrimenti introdurrete deadlock. Idealmente, si otterrebbe il blocco dell'app in modalità S, controllo, l'aggiornamento a X, ma è difficile (per non dire altro ...). L'opzione più sicura è acquisire X, quindi eseguire l'intera distribuzione dello schema DB. Dovrebbe essere un'operazione rara (ad es. All'avvio dell'app), quindi il blocco X non dovrebbe importare molto.
Remus Rusanu,

12

La mia raccomandazione sarebbe quella di fare il meglio per provare / catturare. Gestire il caso duplicato in modo esplicito, a seconda dei casi, ad es. ignoralo...

La vera domanda: perché DDL è in esecuzione su richiesta, da più xact? Normalmente l'aggiornamento e la migrazione sono una cosa seria, gestita in finestre temporali dedicate ... Non vuoi che la tua migrazione (code-first?) Si avvii inaspettatamente, alcuni di quei passaggi di aggiornamento possono richiedere ore su un grande tavolo (dimensione-di -data operazioni ...)


3
Il codice è una specie di DatabaseLogger che crea le sue tabelle su richiesta. Nessuna migrazione, nessun affare divertente. Tuttavia, hai perfettamente ragione. Rifatterò il codice in modo appropriato.
DR

4
Considera anche che la distribuzione / installazione è perfettamente OK per essere eseguita in un contesto con privilegi elevati (ad es. Da un amministratore), ma le normali operazioni non lo sono. Attualmente stai richiedendo una CREATE TABLEsovvenzione per le normali operazioni ...
Remus Rusanu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.