У нас есть таблица MySQL, в которой поле с автоинкрементом установлено как INT (11). Эта таблица в значительной степени хранит список заданий, которые выполняются в приложении. В любой момент времени на протяжении всего жизненного цикла приложения таблица может содержать тысячи записей или быть полностью пустой (т. Е. Все закончено).
Поле не привязано ни к чему другому.
Автоинкремент, по-видимому, случайным образом сбрасывает себя в ноль, хотя нам никогда не удавалось перехватить сброс.
Проблема становится очевидной, потому что мы видим, что поле автоинкремента достигает, скажем, 600 000 записей или около того, а затем, через некоторое время, поле автоинкремента, кажется, работает в нижних 1000.
Это почти как если бы автоинкремент сбрасывал себя, если таблица пуста.
Возможно ли это, и если да, то как его отключить или изменить способ сброса?
Если это не так, есть ли у кого-нибудь объяснение, почему он может это делать?
Благодарность!
источник
Ответы:
http://dev.mysql.com/doc/refman/4.1/en/innodb-auto-increment-handling.html
Из-за этого при перезапуске службы (или сервера) произойдет следующее:
Таким образом, простым языком, после запуска службы MySQL он не знает, каким должно быть значение автоинкремента для вашей таблицы. Поэтому, когда вы впервые вставляете строку, он находит максимальное значение поля, которое использует автоинкремент, добавляет 1 к этому значению и использует полученное значение. Если строк нет, оно начнется с 1.
Это было проблемой для нас, так как мы использовали функцию автоматического увеличения таблицы и mysql для аккуратного управления идентификаторами в многопоточной среде, где пользователи перенаправлялись на сторонний платежный сайт. Таким образом, мы должны были удостовериться, что идентификатор, который третья сторона получила и отправила обратно нам, был уникальным и оставался таким (и, конечно, есть вероятность, что пользователь отменит транзакцию после того, как он будет перенаправлен).
Таким образом, мы создавали строку, получали сгенерированное значение автоинкремента, удаляли строку, чтобы поддерживать чистоту таблицы, и пересылали значение на сайт оплаты. В конечном итоге мы решили исправить проблему, с которой InnoDB обрабатывает значения AI:
При этом всегда сохраняется последний идентификатор транзакции, сгенерированный в виде строки в таблице, без ненужного взрыва таблицы.
Надеюсь, это поможет кому-то еще, кто может столкнуться с этим.
Изменить (2018-04-18) :
Как Finesse упоминается ниже, похоже, что поведение было изменено в MySQL 8.0+.
https://dev.mysql.com/worklog/task/?id=6204
Формулировка в этом рабочем журнале в лучшем случае ошибочна, однако, похоже, что InnoDB в этих более новых версиях теперь поддерживает постоянные значения autoinc при перезагрузках.
-Gremio
источник
Мы столкнулись с этой проблемой и обнаружили, что при запуске таблицы оптимизации для пустой таблицы значение автоинкремента также сбрасывалось. Смотрите этот отчет об ошибке MySQL .
В качестве обходного пути вы можете сделать:
Вместо
OPTIMIZE TABLE
.Кажется, это то, что делает MySQL внутренне (очевидно, без установки значения автоинкремента)
источник
Просто выстрел в темноте - если приложение использует
TRUNCATE TABLE
для очистки таблицы после завершения обработки, это приведет к сбросу поля автоинкремента. Вот краткое обсуждение вопроса. Хотя в этой ссылке упоминается, что InnoDB не сбрасывает auto_increments для усечения, это было сообщено как ошибка и исправлено несколько лет назад.Если предположить, что мои предположения верны, вы можете перейти от усечения к удалению, чтобы устранить проблему.
источник
Только явный сброс этого значения, или удаление / воссоздание этого поля, или другие подобные насильственные операции должны когда-либо сбрасывать счетчик auto_increment. (TRUNCATE была действительно хорошей теорией.) Кажется невозможным, чтобы вы внезапно обернули 32-битный INT, когда последнее значение, которое вы видите, составляет всего 600k. Это определенно не должно сбрасываться только потому, что таблица пуста. У вас либо ошибка MySQL, либо что-то в вашем PHP-коде. Или парень в соседней кабинке подшучивает над тобой.
Вы можете отладить, включив двоичный журнал , так как он будет содержать такие выражения:
Тогда, по крайней мере, вы сможете увидеть все детали того, что происходит с этим столом, в том числе прямо перед сбросом счетчика.
источник
ALTER TABLE table_name ENGINE = MyISAM
Работает на меня. Наш стол всегда очень маленький, поэтому нет необходимости в InnoDB.
источник
InnoDB не сохраняет значение автоинкремента на диске, поэтому забывает его, когда сервер MySQL выключен. Когда MySQL запускается снова, двигатель InnoDB восстанавливает значение автоматическое приращение следующим образом:
SELECT (MAX(id) + 1) AS auto_increment FROM table
. Это ошибка , которая фиксируется в MySQL версии 8.0.Измените движок стола, чтобы решить проблему:
Или обновите сервер MySQL до версии 8.0, когда он будет выпущен.
источник