Domanda

mi sa che l'isolamento dello snapshot sarebbe risolvere questo problema, ma mi chiedo se NOLOCK è sicuro in questo caso specifico in modo che possa evitare il sovraccarico.

Ho una tabella che simile a questa:

drop table Data

create table Data
(
    Id BIGINT NOT NULL,
    Date BIGINT NOT NULL,
    Value BIGINT,
    constraint Cx primary key (Date, Id)
)

create nonclustered index Ix on Data (Id, Date)

Non ci sono aggiornamenti al tavolo, mai. Elimina possono verificarsi, ma non devono mai i conti con il tasto SELECT in quanto influenzano l'altra, estremità più vecchio del tavolo. Gli inserti sono divisioni regolari e di pagina al (Id, Data) Indice sono estremamente comuni.

Ho una situazione di stallo tra un inserto standard e un SELECT che assomiglia a questo:

select top 1 Date, Value from Data where Id = @p0 order by Date desc

perché l'INSERT acquisisce un blocco su Cx (Data, Id, Value) e poi Ix (Id, data), ma SELECT acquisisce un blocco su Ix (Id, Data) e poi Cx (Data, Id; Value) . Questo perché il SELEZIONA cerca prima il IX e poi si unisce a una chiedere il Cx.

scambi l'indice cluster e non cluster potrebbe rompere questo ciclo, ma non è una soluzione accettabile perché introdurrebbe cicli con altri SELECT (più complesse).

Se aggiungo NOLOCK a SELECT, può andare storto in questo caso? Può tornare:

  1. più di una riga, anche se ho chiesto per TOP 1?
  2. Nessuna riga, anche se ne esiste uno ed è stato commesso?
  3. Peggio di tutto, una fila che non soddisfa la clausola WHERE?

Ho fatto un sacco di lettura di questa linea, ma le uniche riproduzioni di anomalie sovra o sotto-count che ho visto ( una , due ) comportano una scansione. Ciò comporta cerca solo. Jeff Atwood ha una post su utilizzando NOLOCK che ha generato una buona discussione. Sono stato particolarmente interessato a un commento di Rick Townsend:

  

In secondo luogo, se si leggono i dati sporchi, il   rischio che si corre è di leggere il   fila completamente sbagliato. Per esempio, se   la vostra selezione Legge un indice per trovare   la riga, quindi l'aggiornamento modifica il   posizione delle righe (es .: a causa di un   divisione di pagina o un aggiornamento della   indice cluster), quando il vostro prescelto   va a leggere la riga di dati reali, è   o non c'è più, o un diverso   fila complessivamente!

Questo è possibile solo con inserti, e non gli aggiornamenti? Se è così, allora credo che anche il mio cerca su un tavolo inserto-solo potrebbe essere pericoloso.


Aggiornamento:

Sto cercando di capire come funziona l'isolamento dello snapshot . Sembra essere basata su file, dove le transazioni leggere la tabella (senza blocco condiviso!), Trovare la riga a cui sono interessati, e poi vedere se hanno bisogno di ottenere una versione della riga dal negozio versione in tempdb.

Ma nel mio caso, nessuna riga avrà più di una versione, in modo che il negozio versione sembra piuttosto inutile. E se la riga è stata trovata senza blocco condiviso, come è diverso da solo utilizzando NOLOCK?

È stato utile?

Soluzione

Utilizzando NOLOCK o READ UNCOMMITTED significa rinunciare a qualsiasi garanzia di coerenza. Periodo.

Se avete bisogno di coerenza, non fare letture sporche. Tutta la tua spiegazione si basa su documentato il comportamento oggetto di modifiche nelle versioni future e, molto peggio, il piani di accesso specifici si aspetta per la query. Query Optimizer è libero di scegliere qualsiasi piano che vede in forma e qualsiasi ipotesi si rendono può essere rotto in produzione. Così è tornato a una piazza:. Non fare letture sporche se non siete preparati ad affrontare le conseguenze

Non sono sicuro se questo vale, non è chiaro che cosa si prova a raggiungere con la query / tavolo, ma forse questo articolo può aiutarvi: Uso di tabelle come code .

Aggiornamento
Dove una lettura NOLOCK leggerebbe uno stato incoerente (ad es. Leggere una chiave di indice non cluster viziata e inseguire ad una riga mancante nel cluster indice) una lettura istantanea troverebbe la riga 'mancante' nella versione. Per i dati stabili, una lettura istantanea è identico a un nolock leggere. La magia del negozio versione entra in gioco ogni volta che i dati vengono modificati (aggiornamenti non impegnati), perché la lettura snapshot va in archivio versione e trova i valori di 'vecchi' (stabile e coerente), dove la lettura nolock sarebbe andato in tilt e Chase puntatori in lala terra.

Altri suggerimenti

Si dovrebbe essere al sicuro con il NOLOCK in questo caso. Un pensiero in più:. L'aggiunta di valore come una colonna inserita nell'indice Ix dovrebbe eliminare la cercano sul Cx

create nonclustered index Ix on Data (Id, Date) include (Value)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top