MySql upsert e di incremento automatico provoca lacune
Domanda
Ho una tabella MySQL con una chiave primaria di auto-incremento, e sembra che tutti i vari metodi upsert (INSERT ignorare e ON DUPLICATE KEY UPDATE) Soffro, uh, caratteristica che il campo di incremento automatico incrementi, anche se una riga viene aggiornata e non inseriti. Ciò significa che le lacune vengono introdotti nella tabella, che trovo indesiderabile.
Quindi la domanda è: esiste un modo per upsert record in una tabella con un campo di incremento automatico senza incremento automatico quel campo, se l'upsert infatti semplicemente aggiorna la fila. A mio parere, questo è il modo upsert dovrebbe comportarsi, ma non sembra.
Soluzione
Questo "problema" è solo in InnoDB
.
E 'di progettazione, e destinato a migliorare la concorrenza:. Un altro thread può utilizzare un AUTO_INCREMENT
, senza dover attendere i risultati di un'operazione UPSERT
Dopo un avvio del server, per il primo inserimento in una
t
tavolo,InnoDB
esegue l'equivalente di questa affermazione:SELECT MAX(ai_col) FROM t FOR UPDATE;
...
inizializza
InnoDB
ma non incrementa il valore e lo memorizza per l'uso da inserti successivi...
Quando si accede al contatore di incremento automatico,
InnoDB
utilizza una speciale serratura a livello di tabellaAUTO-INC
che mantiene fino alla fine della dichiarazioneSQL
corrente, non alla fine della transazione. La strategia di sblocco speciale è stato introdotto per migliorare la concorrenza per inserti in una tabella contenente una colonnaAUTO_INCREMENT
. Tuttavia, due operazioni non possono avere il bloccoAUTO-INC
sulla stessa tabella simultaneamente, che può avere un impatto sulle prestazioni se il bloccoAUTO-INC
viene mantenuto per lungo tempo. Questo potrebbe essere il caso di una dichiarazione comeINSERT INTO t1 ... SELECT ... FROM t2
che inserisce tutte le righe da una tabella all'altra.
MyISAM
non presenta questo comportamento, poiché dell'algoritmo AUTO_INCREMENT
diversa implementazione (a causa della sua limitata capacità di supportare DML
concorrente).