Domanda

Di ', ho una tabella persona e ha solo 1 fila -

id = 1, name = 'foo'

In una connessione

select p1.id, p1.name, p2.name
from person p1 
join person p2 on p1.id = p2.id

In un altro collegamento allo stesso tempo:

update person set name = 'bar' where person.id = 1

Q1: È mai possibile, per il mio selezionare per restituire un risultato come questo in base alla tempistica della dichiarazione di aggiornamento:

id = 1, p1.name = 'foo', p2.name = 'bar'

Né connessione utilizza una transazione esplicita ed entrambi livello di isolamento di difetto di uso LEGGI commesso.

La domanda è: è davvero di aiutarmi a capire, se i blocchi acquisiti all'inizio di un'istruzione SQL continuano ad esistere fino al completamento istruzione, o se è possibile che una dichiarazione per rilasciare il blocco e ri-acquisire il blocco per la stessa riga se viene utilizzato due volte nella stessa istruzione?

Q2:? Se la soluzione al cambiamento domanda se il set read_committed_snapshot on è impostato sul db

È stato utile?

Soluzione

Q1: Sì, questo è perfettamente possibile, almeno in teoria. read committed garantisce solo che tu non leggere dati sporchi che non fa promesse di coerenza. A livello impegnati leggere blocchi condivisi vengono rilasciati non appena i dati vengono letti (non alla fine della transazione o anche la fine dell'istruzione)

Q2: Sì, la risposta a questa domanda sarebbe cambiare se read_committed_snapshot è acceso. Si potrebbe quindi essere garantito livello di istruzione di coerenza. Sto trovando difficoltà a trovare una fonte online che indica in modo inequivocabile questo, ma citando p.648 di "Microsoft SQL Server 2008 Internals"

Una dichiarazione in RCSI vede tutto commesso prima dell'inizio della dichiarazione. Ogni nuova dichiarazione in raccoglie transazione fino al più recente cambiamenti inseriti.

vedere questo MSDN post sul blog

Impostazione script

CREATE TABLE person 
(
id int primary key,
name varchar(50)
)

INSERT INTO person
values(1, 'foo');

Connessione 1

while 1=1
update person SET name = CASE WHEN name='foo' then 'bar' ELSE 'foo' END

Connessione 2

DECLARE @Results TABLE (
  id    int primary key,
  name1 varchar(50),
  name2 varchar(50))

while( NOT EXISTS(SELECT *
                  FROM   @Results) )
  BEGIN
      INSERT INTO @Results
      Select p1.id,
             p1.name,
             p2.name
      from   person p1
             INNER HASH join person p2
               on p1.id = p2.id
      WHERE  p1.name <> p2.name
  END

SELECT *
FROM   @Results  

Risultati

id          name1 name2
----------- ----- -----
1           bar   foo

Guardando l'altro tipi di join in Profiler sembra che la questione non poteva nascere sotto sia la merge aderire o piano nested loops per questo particolare query (serrature vengono rilasciati fino a quando tutti sono acquisiti), ma i resti di punti che read committed solo vi garantisce non leggere dati sporchi che non fa promesse circa la coerenza. In pratica si può anche non avere questo problema per la query esatto avete pubblicato come SQL Server non sarebbe scegliere questo tipo si uniscono per impostazione predefinita. Tuttavia si sono poi appena lasciato basandosi su dettagli di implementazione per produrre il comportamento che si desidera.

 Trace

NB: Se vi stavate chiedendo il motivo per cui alcuni blocchi a livello di riga S sembrano mancare questo è un'ottimizzazione spiegato qui .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top