2010-05-07 4 views
32

Un collega mi ha appena reso consapevole di un comportamento MySQL molto strano.Perché l'incremento automatico di MySQL aumenta in caso di inserimenti non riusciti?

Supponendo di disporre di una tabella con un campo auto_increment e un altro campo impostato su univoco (ad esempio un campo nome utente). Quando si tenta di inserire una riga con un nome utente già presente nella tabella, l'inserimento non riesce, come previsto. Tuttavia, il valore auto_increment è aumentato come si può vedere quando si inserisce una nuova voce valida dopo diversi tentativi falliti.

Per esempio, quando la nostra ultima voce assomiglia a questo ...

ID: 10 
Username: myname 

... e cerchiamo cinque new entry con lo stesso valore di nome utente sulla nostra prossima inserto avremo creato una nuova riga come così:

ID: 16 
Username: mynewname 

Anche se questo non è un grosso problema in sé sembra un vettore di attacco molto stupido per uccidere un tavolo da inondazioni con le richieste di inserimento falliti, come i MySQL riferimento stati manuali:

"Il comportamento del meccanismo di auto-incremento non è definito se [...] il valore diventa maggiore del numero intero massimo che può essere memorizzato nel tipo di intero specificato."

È questo comportamento previsto?

+6

vostro vettore di attacco sembra un non problema. Se potessi invaderlo con richieste di inserimento non riuscite, potresti ugualmente invaderlo con richieste non riuscite? –

+0

puoi portare un codice ** di riproduzione invece di spiegazioni manuali? –

+4

@martin smith: Anche se è vero, penso che un'improvvisa ondata di nuovi utenti sarebbe più ovvia di un aumento silenzioso dell'auto_incremento che potrebbe benissimo cadere nel dimenticatoio se non fosse stato controllato. – Sorcy

risposta

23

InnoDB è un motore transazionale.

Ciò significa che nel seguente scenario:

  1. Session A inserti registrazione 1
  2. Session B inserti registrazione 2
  3. Session A cilindri di appoggio

, non v'è né la possibilità di un gap oppure session B si bloccherebbe fino al session A commesso o annullato.

InnoDB I progettisti (come la maggior parte degli altri progettisti di motori transazionali) hanno scelto di lasciare spazi vuoti.

Dal documentation:

Quando si accede al contatore di incremento automatico, InnoDB utilizza uno speciale-livello di tabella AUTO-INC di blocco che mantiene fino alla fine della corrente SQL dichiarazione, non alla fine della transazione . La strategia di sblocco speciale è stato introdotto per migliorare la concorrenza per gli inserimenti in una tabella che contiene una colonna AUTO_INCREMENT

...

InnoDB utilizza il contatore di incremento automatico in memoria fino a quando viene eseguito il server. Quando il server viene arrestato e riavviato, InnoDB reinizializza il contatore per ogni tabella per il primo INSERT nella tabella, come descritto in precedenza.

Se avete paura della confezione id colonna di giro, renderla BIGINT (lunga 8 byte).

+1

La tua risposta mi ha aiutato molto con il mio problema. Grazie. c'è un modo per aggirare questo comportamento di InnoDB per quanto riguarda l'autoincremento? – Aufwind

+0

stessa domanda di Aufwind. –

+1

@Ankit: per favore postalo come un'altra domanda e metti un link qui. – Quassnoi

4

Senza conoscere l'interno esatto, direi di sì, l'auto-incremento DOVREBBE consentire che i valori saltati facciano errori negli inserimenti. Diciamo che stai facendo una transazione bancaria, o altro in cui l'intera transazione e più record vanno come un "tutto o niente". Se si prova il proprio inserto, ottenere un ID, quindi timbrare tutti i dettagli successivi con quell'ID transazione e inserire i record di dettaglio, è necessario garantire l'univocità qualificata. Se hai più persone che sbattono il database, anche loro dovranno assicurarsi di ottenere il proprio ID della transazione in modo da non entrare in conflitto con il tuo quando la transazione viene commessa. Se qualcosa non riesce nella prima transazione, nessun danno fatto, e nessun elemento pendente a valle.

+0

è l'uso di questa natura skkiping di incremento automatico ma voglio sapere è questo qualsiasi modo per fermare questo skipaggio –

+2

@Ankit, no, non è possibile interrompere il salto. L'intestazione del file che tiene traccia dell'ultimo ID assegnato è sempre incrementata. Se c'è un problema e 10 persone stanno inserendo transazioni e 3 interrompono, non vorrai mai eseguire il backfill di questa transazione interrotta solo per usare un ID. – DRapp

+0

grazie per la cancellazione del dout –

-1

So che questo è un vecchio articolo ma poiché non sono riuscito a trovare la risposta giusta, ho trovato un modo per farlo. È necessario avvolgere la query all'interno di un'istruzione if. Il suo solito inserire query o inserire e sulla querys duplicati che rovinare l'ordine organizzato incremento automatico in modo per inserti regolari usano:

invece di INSERIRE ED ON DUPLICATE utilizzare un set UPDATE WHERE QUERY dentro o fuori di un if non ha importanza e un REPLACE INTO QUERY fa anche sembra funzionare

+2

Sto facendo downvoting di questa risposta poiché non è affatto applicabile. Sì, è possibile verificare se esiste un record prima di provare l'inserimento, ma questo è completamente al di là del punto. – Mave

Problemi correlati