Почему INSERT IGNORE увеличивает первичный ключ auto_increment?
Я написал java-программу, которая обращается к базе данных innodb MySQL.
Всякий раз, когда оператор INSERT IGNORE встречает дублируемую запись, первичный ключ Auto Increment увеличивается.
Ожидается ли такое поведение? Я думаю, что это не должно происходить с IGNORE. Это означает, что IGNORE фактически несет дополнительные накладные расходы для записи нового значения первичного ключа.
Таблица выглядит следующим образом:
CREATE TABLE `tablename` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`rowname` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `rowname` (`rowname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Спасибо!
Ответы
Ответ 1
Это поведение по умолчанию с MySQL 5.1.22.
Вы можете установить конфигурационную переменную innodb_autoinc_lock_mode
на 0
(также известный как "традиционный" режим блокировки). Если вы хотите избегайте пробелов в столбцах автоматического увеличения. Тем не менее, это может привести к снижению производительности, поскольку этот режим приводит к блокировке таблицы до завершения INSERT
.
Из документов на InnoDB AUTO_INCREMENT Режимы блокировки:
innodb_autoinc_lock_mode = 0
( "традиционный" режим блокировки)
Традиционный режим блокировки обеспечивает такое же поведение, которое существовало перед параметром конфигурации innodb_autoinc_lock_mode
представленный в MySQL 5.1. Предусмотрен режим традиционной блокировки для обратной совместимости, тестирования производительности и работы проблемы со "вставками смешанного режима" из-за возможных различий в семантика.
В этом режиме блокировки все операторы типа "INSERT" получают специальный столовый уровень AUTO-INC
блокировка для вставок в таблицы с AUTO_INCREMENT
колонны. Этот замок обычно удерживается в конце инструкции (не до конца транзакции), чтобы гарантировать, что значения автоинкремента назначаются в предсказуемом и повторяемом порядке для данного последовательности операторов INSERT
и обеспечить автоматическое увеличение значения, присваиваемые любым заданным оператором, являются последовательными.
Ответ 2
Я считаю, что это настраиваемый параметр в InnoDB. Смотрите: AUTO_INCREMENT Обработка в InnoDB
Вы хотите пойти с
innodb_autoinc_lock_mode = 0
Ответ 3
Я думаю, что это поведение разумно. На автоматическое приращение не следует полагаться, чтобы дать последовательности, которые не имеют пробелов.
Например, откат транзакции по-прежнему потребляет идентификаторы:
INSERT INTO t (normalcol, uniquecol) VALUES
('hello','uni1'),
('hello','uni2'),
('hello','uni1');
Очевидно, генерирует уникальное нарушение ключа и не вставляет никакие строки в базу данных (предполагая здесь транзакционный движок). Тем не менее, он может потреблять до 3 значений автоинкремента, не вставляя ничего.
Ответ 4
Не уверен, ожидал ли он, хотя я бы рекомендовал переключиться на:
INSERT ... ON DUPLICATE KEY UPDATE