MySQL - L'incremento automatico non aumenta in sequenza se l'ultima riga è stata eliminata


8

Ho una tabella che contiene un ID chiave primaria auto incrementato. Se elimino l'ultima riga (ID più alto, per ID esempio = 6) e inserisco una nuova riga, il nuovo ID inizia da 7. Quale parametro devo modificare e la chiave primaria inizia da 6?

CREATE TABLE animals (
 id MEDIUMINT NOT NULL AUTO_INCREMENT,
 name CHAR(30) NOT NULL,
 PRIMARY KEY (id)
) ENGINE=MyISAM;

INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');

Risultato:
nome id
1 cane
2 gatto
3 pinguino
4 lassù
5 balena
6 struzzo

DELETE FROM animals WHERE id = 6;
INSERT INTO animals (name) VALUES
('x');

Risultato:
nome id
1 cane
2 gatto
3 pinguino
4 lassù
5 balena
7 x

Grazie per il consiglio.


E se ci fossero delle lacune? (che può apparire a causa di diversi altri motivi, non solo eliminando le righe)
ypercubeᵀᴹ

cosa ti piacerebbe fare se la cancellazione avviene dopo qualche inserimento? hai intenzione di riutilizzare quel divario? è sì, allora non credo che Identity sia il tipo giusto per quella colonna. ti dà l'opportunità di non preoccuparti di valori univoci in quella colonna. se si intende mantenere i valori in sequenza, è possibile utilizzare il normale tipo di dati di tipo INT / BIGINT. trovare / riutilizzare / reimpostare i valori per ogni gap mancante è come rinunciare allo scopo della proprietà dell'identità.
Anup Shah,

@giordano Perché vuoi essere un maniaco della PRIMARY KEY AUTO_INCREMENT? risolverlo c'è anche un "gap" nei dati della tabella se si aggiorna / elimina a causa della frammentazione ..
Raymond Nijland

Qualche tempo fa ho fatto un'indagine sui valori continui di auto_increment per SQL Server: sqlity.net/it/792/the-gap-in-the-identity-value-sequence - Anche se non è per MySQL, i meccanismi sottostanti sono gli stessi , quindi otterrai risultati simili. In breve, non è possibile evitare lacune e sequenze generate automaticamente.
Sebastian Meine,

@ypercube: grazie per le risposte. In effetti, il divario che ho ottenuto da un altro esempio più complesso, ma volevo mostrare un esempio minimo. Il vero esempio era (1) cambiare la data di scadenza di una riga (ad es. Da una tabella di prodotti) a causa della modifica di un attributo e (2) aggiungere il nuovo prodotto con lo stesso codice prodotto, nuovo attrribute, nuova data di validità e scadenza aperta Data. Quello che è successo è che la nuova chiave primaria non è stata incrementata automaticamente con +1 ma +2. Ovviamente, nel passaggio (1) o (2) c'è un incremento automatico invisibile. Mi chiedo quali sono gli altri motivi per le lacune.
giordano,

Risposte:


12

Questo è in base alla progettazione: tutti i DBMS agiscono in questo modo con colonne con incremento automatico.

Se non lo facessero, l'integrità referenziale esterna potrebbe essere danneggiata. Per un semplice esempio di ciò, immagina di archiviare gli URL per un servizio di accorciamento utilizzando una colonna di incremento automatico come chiave. Non sai se l'URL abbreviato è stato ancora distribuito a nessuno, e il database certamente no, quindi il riutilizzo dell'ID 1234 potrebbe comportare che la povera nonna di qualcuno visiti somenastypornsite.xxx invece di loverlyknitting.org quando fa clic su http: / /shortthi.ng/1234 in una vecchia email, invece di ricevere un messaggio "scusa ma questo link non esiste più nei nostri archivi".

Inoltre, se ripristini l'incremento dopo aver eliminato l'ultimo elemento, eseguirai anche tutto il lavoro (o ti aspetti che il database sia) di rinumerare tutto dopo il 5 ° elemento di 5 milioni quando il 5o elemento viene rimosso? completo di modifiche ad altre tabelle in cui sono i vincoli di chiave esterna che puntano alla colonna di incremento? Tale lavoro extra potrebbe diventare molto costoso per quanto riguarda l'IO.

Se fai ripristinare il punto di incremento dopo l'eliminazione l'ultimo elemento, si deve essere molto, molto attenti dei vostri livelli di isolamento delle transazioni: Si potrebbe ripristinare solo come un'altra transazione si avvale del valore, che porta ad errori (o, errori silenti peggio), a meno che ti assicuri che la tua azione sia completamente isolata al 100%.

In genere consiglio alle persone che lavorano con i database di leggere "SQL Antipatterns" che contiene un capitolo su questo problema chiamato "Psuedo-Key Neat Freaks" (che tratta la questione in modo più amichevole di quanto il titolo del capitolo possa implicare per alcuni!). In sostanza, se il valore ha un significato oltre ad essere una chiave (o al massimo portando informazioni sull'ordine di inserimento), probabilmente non dovrebbe essere una colonna auto-incrementante, e se non ha alcun significato oltre ad essere una chiave (o al massimo portando un ordine di inserimento informazioni), quindi le lacune non dovrebbero avere importanza.


Grazie per questa spiegazione Vedo che devo approfondire il concetto chiave. Mi chiedo come funzioni il meccanismo di incremento automatico, poiché ho osservato anche lacune nella chiave primaria quando non l'ho cancellata ma ho cambiato (aggiornato) una riga e ne ho aggiunta una nuova. Sicuramente, ciò che non farò è cambiare manualmente il valore di incremento automatico.
giordano,

Riguardo a "approfondire il concetto chiave", consiglio vivamente il libro SQL Antipatterns di Bill Karwin - che tratta questo e una serie di altri argomenti comuni (e non così comuni), parlando di come sbagliare, perché l'errore comune i metodi possono causare problemi, come risolverli e quando il metodo "sbagliato" potrebbe essere OK da usare (o l'unica scelta) comunque, in modo conciso ma accessibile.
David Spillett,

Spillet: grazie per questa indicazione. Ho letto ora ed è stato molto utile. Tuttavia, non capisco perché InnoDB e MyISAM contino diversamente: dba.stackexchange.com/questions/51883/…
giordano,

0

È possibile reimpostare il valore auto_increment utilizzando quanto segue:

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

Dovresti determinare il valore massimo presente nella tabella e aggiungere 1 a quel valore da utilizzare nell'istruzione precedente.


Cattiva idea questo bloccherà il tuo tavolo dalla lettura o dalla scrittura in "quasi tutte" le versioni di MySQL. MySQL 5.6 potrebbe eseguire un ALTER LIVE ma a volte deve anche bloccare la tabella.
Raymond Nijland,

2
@RaymondNijland Non credo che il lucchetto durerebbe abbastanza a lungo da essere notato da chiunque.
ypercubeᵀᴹ

@ Max, Raymond, ypercube: grazie per la risposta. Eviterò di fare questo tipo di cambiamento.
giordano,
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.