Почему 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