2012-12-01 9 views
7

Non ho mai visto accadere prima, molto strano.Odd SQL Server 2012 problema IDENTITY

Ho un database locale di SQL Server 2012 Express sto sviluppando contro. Esecuzione di una semplice suite di test utilizzando il plug-in TestDrive e accesso al database con EF v5.

Ho appena eseguito un test che inserisce un record nel database. Ho avuto 9 righe nella tabella andando da id 1-9. Il prossimo inserimento e l'ID sono saltati esattamente esattamente 10000 !!!!

La colonna Id va:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10009 

So fallito inserti anche incrementare l'ID, ma posso garantire che 10.000 non ha mancato di inserire nei 5 secondi tra test viene eseguito ...

La struttura della tabella è davvero semplice, un gruppo di colonne e una colonna di incremento automatico, identità di tipo bigint (lunga), senza SP, trigger o qualsiasi altro contenuto programmatico.

[Id] [bigint] IDENTITY(1,1) NOT NULL, 

Molto confuso, qualcun altro ha visto accadere questo?

+0

non vedo come possa essere il mio codice. Il codice non fa nulla con l'ID ed è un comando INSERT, non un comando UPDATE e se l'INSERT ha provato ad applicare un ID semplicemente ignorerebbe il valore dell'ID ... – Jammer

+0

Sembra che questo potrebbe essere un bug nel 2012 perché è riportato qui da altri pure ... http://connect.microsoft.com/SQLServer/feedback/details/743300/identity-column-jumps-by-seed-value#tabs Ho appena aggiunto un log per questo come beh ... – Jammer

+0

Sembra causato da un riavvio del motore SQL ... ma perché sarebbe saltato 10000 quando il mio seme è 1 è un po 'pazzo ... – Jammer

risposta

2

Questo blog post ha alcuni dettagli aggiuntivi. Sembra che nel 2012, identity sia implementato come una sequenza. E per impostazione predefinita, una sequenza ha una cache. Se la cache viene persa, si perdono i valori della sequenza nella cache.

La soluzione proposta è quella di creare una sequenza con no cache:

CREATE SEQUENCE TEST_Sequence 
    AS INT 
    START WITH 1 
    INCREMENT BY 1 
    NO CACHE 

Per quanto posso vedere, la sequenza dietro una colonna di identità è invisibile. Non è possibile modificare le sue proprietà per disabilitare la memorizzazione nella cache.

Per utilizzarlo con Entity Framework, è possibile impostare StoredGeneratedPattern della chiave primaria su Computed. Poi si potrebbe generare il lato server identità in un instead of insert innesco:

if exists (select * from sys.sequences where name = 'Sequence1') 
    drop sequence Sequence1 
if exists (select * from sys.tables where name = 'Table1') 
    drop table Table1 
if exists (select * from sys.triggers where name = 'Trigger1') 
    drop trigger Trigger1 
go 
create sequence Sequence1 
    as int 
    start with 1 
    increment by 1 
    no cache 
go 
create table Table1 
    (
    id int primary key, 
    col1 varchar(50) 
    ) 
go 
create trigger Trigger1 
    on Table1 
    instead of insert 
as 
insert Table1 
     (ID, col1) 
select next value for Sequence1 
,  col1 
from inserted 
go 
insert Table1 (col1) values ('row1'); 
insert Table1 (col1) values ('row2'); 
insert Table1 (col1) values ('row3'); 

select * 
from Table1 

Se si trova una soluzione migliore, fatemelo sapere :)

+0

Ahhh ... è interessante. Vedrò se riesco a ottenere questo approccio senza cache lavorando con EF ... – Jammer

+0

Hmm ...tutto mi sembra un po 'disordinato :(Vedrò se riesco a trovare qualcosa al riguardo e riferire in merito – Jammer

+0

In realtà, sai una cosa, non sono nemmeno sicuro che mi interessi, è un bigint quindi non ho intenzione di I miei Ids non vengono utilizzati in alcun modo che dipende da come vengono creati e se succede solo quando SQLServer viene riavviato in produzione che non sarà spesso (famose ultime parole!) ... almeno io Non sono preoccupato ora, potrebbe benissimo tornare al 2008 R2 per un vero schieramento di produzione ... – Jammer

0

Se si chiamerà "Checkpoint" comando dopo ogni query di inserimento, risolverà il tuo problema.

Per ulteriori informazioni, si prega di leggere il Checkpoint in SQL Server

+0

Ci sono circa 300 query di inserimento nel DB. non funzionerebbe, MS ha bisogno di risolvere questo problema. –