To zachowanie jest udokumentowane (akapit w nawiasach):
Jeśli określisz ON DUPLICATE KEY UPDATE i zostanie wstawiony wiersz, który spowodowałby zduplikowaną wartość w indeksie UNIQUE lub PRIMARY KEY, MySQL przeprowadza aktualizację starego wiersza. Na przykład, jeśli kolumna a jest zadeklarowana jako UNIQUE i zawiera wartość 1, następujące dwie instrukcje mają podobny skutek:
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
(Efekty nie są identyczne dla tabeli InnoDB, gdzie a jest kolumną z automatycznym przyrostem. W przypadku kolumny z automatycznym przyrostem, instrukcja INSERT zwiększa wartość automatycznego zwiększania, ale UPDATE nie.)
Oto proste wyjaśnienie. MySQL próbuje najpierw wykonać wstawienie. To jest, gdy identyfikator jest automatycznie zwiększany. Raz zwiększona, pozostaje. Następnie wykrywany jest duplikat i następuje aktualizacja. Ale wartość zostaje pominięta.
Nie powinieneś polegać na auto_increment
bez luk. Jeśli jest to wymagane, koszty związane z aktualizacjami i wstawkami są znacznie większe. Zasadniczo musisz nałożyć blokadę na całą tabelę i zmienić numerację wszystkiego, co wymaga zmiany numeracji, zwykle za pomocą wyzwalacza. Lepszym rozwiązaniem jest obliczenie wartości przyrostowych na wyjściu.