it-roy-ru.com

Будет ли MySQL повторно использовать удаленные идентификаторы при применении автоматического увеличения

http://dev.mysql.com/doc/refman/5.0/ru/example-auto-increment.html

Этот документ, который я читаю, говорит что-то вроде:

«В этом случае (когда столбец AUTO_INCREMENT является частью индекса из нескольких столбцов) значения AUTO_INCREMENT используются повторно, если вы удаляете строку с наибольшим значением AUTO_INCREMENT в любой группе».

Я не очень понимаю, что там говорится. Разве значения не должны использоваться повторно автоматически?

Заранее спасибо...

19
Eae

InnoDB сбрасывает поле auto_increment при перезапуске базы данных. 

Когда InnoDB перезапускается, он находит самое высокое значение в столбце и затем начинает отсюда. 

Это не произойдет в MyISAM, потому что он кэширует последний увеличенный идентификатор.

Обновление

Эта функция/ошибка существует с 2003 года и может привести к серьезным проблемам. Возьмите пример ниже,

  1. Таблица t1 имеет первичный ключ auto-inc.

  2. Таблица t2 имеет столбец для первичного ключа в t1 без внешнего ключа «ограничение». Другими словами, когда строка удаляется в t1, соответствующие строки в t2 становятся сиротами.

  3. Как мы знаем при перезапуске InnoDB, идентификатор может быть переиздан. Поэтому потерянные строки в t2 могут быть ложно связаны с новыми строками в t1.

Эта ошибка была окончательно исправлена ​​в MySQL 8.0.0WL # 6204 - InnoDB Постоянное максимальное значение для столбцов автоинхронизации .

InnoDB будет отслеживать максимальное значение и сохранять при перезагрузке это максимальное значение и начать оттуда.

15
rAjA

Если у вас есть поле первичного ключа, которое также является auto_increment, независимо от того, сколько строк (или в каком порядке) удалено, идентификаторы, которые больше не существуют, больше не используются, и поле непрерывно увеличивается для каждой строки.

Однако, когда ваш первичный ключ состоит из нескольких полей (например, поле auto_increment и другое поле), поле auto_increment используется повторно, и только когда удаленный идентификатор является последним идентификатором. Это означает, что если у вас есть значения, такие как 1, 2, 3, 4 и 5, и вы удалите строку со значением поля 5, следующая строка будет иметь идентификатор 5. Однако, если вы удалите строку с идентификатор 2, опять же, он не будет использоваться, а следующий ряд будет иметь идентификатор 6.

8
Parham Doustdar

Как описано с механизмом InnoDB, последний использованный PK будет повторно использован, если строка будет удалена до перезагрузки, поскольку она не кэшируется. Если этот PK является внешним ключом (FK) в другой таблице, могут возникнуть проблемы (FK hell). Вот как я обнаружил проблему, когда маленькая старушка пролетела до 195 см (!), Когда были отобраны дополнительные данные удаленного человека. Обойти это можно либо для реализации «ON DELETE CASCADE» для дочерних таблиц, либо (не мой предпочтительный вариант) для кодирования этой проблемы.

2
OldSteve

Если таблица имеет тип InnoDB, то удаленные идентификаторы повторно используются в определенных сценариях. Вот что я сделал, чтобы проверить это:

  1. Пользователь таблицы имеет столбец идентификатора в качестве первичного ключа с установленным auto_increment

    CREATE TABLE user ( id bigint (20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id), ) ENGINE = InnoDB AUTO_INCREMENT = 2108 DEFAULT CHARSET = latin1;

  2. Мой вызов API createUser, создает запись в пользовательской таблице. Допустим, пользователь с id = 1 создан.

  3. Вызовите deleteUser API, который просто удаляет строку из пользовательской таблицы.

  4. Остановите и запустите базу данных

  5. Вызовите createUserAPI еще раз. Создает пользователя с таким же идентификатором (id = 1). 

Таким образом, он использует удаленный идентификатор, если сервер перезапускается . Я получил эту проблему, потому что у меня была другая таблица с именем user_rules, которая хранила user_id в столбце, но у нее не было ссылки FK на пользовательскую таблицу (что было неправильно ). Другая проблема заключалась в том, что когда пользователь удалялся, запись из таблицы user_rules не удалялась, и, поскольку у него не был установлен FK, db также не жаловался .. И когда сервер был перезапущен, пользовательские правила были испорчены!

0
user1270392

Как уже упоминалось в ответ :

InnoDB сбрасывает поле auto_increment при перезапуске базы данных.

Когда InnoDB перезапускается, он находит самое высокое значение в столбце и затем начинает с него. 

и такое поведение может привести к проблеме внешнего ключа.

К счастью, из MySQL 8.0.0 это будет исправлено. Больше информации:

Ошибка # 199 Статистика автоинкремента Innodb теряется при перезагрузке

WL # 6204: постоянное максимальное значение InnoDB для столбцов autoinc

Смотрите Ошибка № 199 об ошибках MySQL.

В настоящее время InnoDB делает следующее, когда таблица открывается: ВЫБЕРИТЕ МАКС. (c) ОТ t; где c - имя столбца AUTOINC . Этот шаг используется для инициализации следующего значения autoinc столбца и распределение значений autoinc начинается с этой точки. InnoDB также делает это когда он выполняет «ALTER TABLE AUTO_INCREMENT = N;».

...

InnoDB должен отслеживать максимальное значение и сохранять при перезагрузке это максимальное значение и начать оттуда.

0
Lukasz Szozda