Что происходит, когда auto_increment для целочисленного столбца достигает max_value в базах данных?

Я реализую приложение базы данных, и я буду использовать как JavaDB, так и MySQL в качестве базы данных. У меня есть столбец идентификатора в моих таблицах, который имеет тип integer, и я использую функцию auto_increment базы данных для значения.

Но что произойдет, если я получу более 2 (или 4) миллиардов сообщений, а целого числа будет недостаточно? Является ли целое число переполненным и продолжается, или это исключение, которое я могу обработать?

Да, я могу изменить тип данных на long, но как мне проверить, когда это необходимо? И я думаю, что есть проблема с получением функций last_inserted_id(), если я использую тип данных long для столбца ID.


person Jonas    schedule 10.04.2010    source источник


Ответы (6)


Комментарий Джима Мартина из §3.6.9. "Использование AUTO_INCREMENT" документации MySQL:

На всякий случай, если возникнут вопросы, поле AUTO_INCREMENT /DOES NOT WRAP/. Как только вы достигнете предела размера поля, INSERT выдаст ошибку. (Со слов Джереми Коула)

Быстрый тест с MySQL 5.1.45 приводит к ошибке:

ОШИБКА 1467 (HY000): не удалось прочитать значение автоинкремента из механизма хранения.

Вы можете проверить эту ошибку при вставке и принять соответствующие меры.

person outis    schedule 11.04.2010
comment
Как я вижу в своих тестах, генерируемое число приращений всегда одинаково (максимальное значение) после достижения предела. Я не получаю ошибку SQL, как ожидалось. - person Victor; 12.02.2019

Просто, чтобы успокоить нервы, подумайте об этом:

Предположим, у вас есть база данных, которая вставляет новое значение каждый раз, когда пользователь выполняет какую-либо транзакцию на вашем веб-сайте.

С 64-битным целым числом в качестве идентификатора это является условием для переполнения: при населении мира в 6 миллиардов, тогда, если каждый человек на земле выполняет транзакцию один раз в секунду каждый день и каждый год (без отдыха), это займет более 80 лет для вашего идентификатора, чтобы обернуть вокруг.

Т.е. только гуглю нужно изредка во время кофе-брейка невнятно рассматривать эту проблему.

person Justin    schedule 16.05.2011
comment
Извините, если быть точным, это займет более 9 лет :) Через 1 минуту произойдет 360 bill tnx. Через 1 час 21600 купюр. За 1 день будет проверено 518400 миллиардов tnx. 1 год: 1892160 тысяч миллиардов. Через 8 лет в бд будет сохранено 15 137 280 тысяч миллиардов. Лимит UNSIGNED BIGINT составляет 18 446 744 тысячи миллиардов. - person tobia.zanarella; 03.07.2012
comment
вы получаете этот один ноль дополнительно в течение 1 года. так что будет 97 лет ок. - person lockedscope; 27.06.2013
comment
А что, если у меня есть 2000 прокси, выполняющих атаку вставки, запускающую несколько потоков/запросов? . Или, например, у меня есть функция загрузки истории с (60 000 записей), поэтому для загрузки этой истории потребуется меньше запросов. - person Anestis Kivranoglou; 24.01.2014
comment
Я задавался этим вопросом уже давно (например, 2 года, LOL). Каково решение этого, если это произойдет? Что, если предположительно 1 миллиард активных пользователей Facebook комментирует по крайней мере 3 раза в день, и эти комментарии находятся только в одной таблице с ее идентификатором, установленным как int (11), какое решение, если он достигает максимального значения столбца? Кажется, это проблема для размышлений, по крайней мере, для Facebook. - person christianleroy; 25.01.2016
comment
ну для меня, int(10) unsigned, столбец id достиг 237836414 всего за 2 месяца или 5,54% от uint_max. Итак, это проблема. - person majidarif; 07.06.2017
comment
@majidarif с такой скоростью, если вы вместо этого используете BigInt, вам потребуется дополнительно 77 560 638 270 месяцев, чтобы использовать все возможные значения, или 6,5 миллиардов лет плюс-минус пара миллионов лет. - person Franck; 23.09.2017
comment
Итог: когда верхняя граница неизвестна, просто используйте BIGINT (или 64-битные целые числа для программистов). Это основное эмпирическое правило для всего в вычислительной технике. Все еще связанный, но реально неуместный. - person William T Froggard; 26.11.2017
comment
Лучшим вариантом будет использование уникальных строк, таких как '6e894c6a-a02a-46ba-b2aa-de0d66d13293', '446a571b-d61f-4dae-bc6d-df1cc2ab52c2'. В случае python модуль uuid позволяет нам сгенерировать это, то есть используя str(uuid.uuid4()). - person hygull; 01.08.2019

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

На самом деле, для начала вы должны проектировать с достаточно большим типом данных. Производительность вашей базы данных не пострадает, даже если вы с самого начала используете 64-битный идентификатор.

person Matti Virkkunen    schedule 10.04.2010

В ответах здесь указано, что происходит, но только в одном ответе говорится, как обнаружить проблему (и то только после того, как ошибка произошла). Как правило, полезно иметь возможность обнаруживать эти вещи до того, как они станут проблемой в производственной среде, поэтому я написал запрос, чтобы определить, когда вот-вот произойдет переполнение:

SELECT
  c.TABLE_CATALOG,
  c.TABLE_SCHEMA,
  c.TABLE_NAME,
  c.COLUMN_NAME
FROM information_schema.COLUMNS AS c
JOIN information_schema.TABLES AS t USING (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME)
WHERE c.EXTRA LIKE '%auto_increment%'
  AND t.AUTO_INCREMENT / CASE c.DATA_TYPE
      WHEN 'TINYINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 255, 127)
      WHEN 'SMALLINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 65535, 32767)
      WHEN 'MEDIUMINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 16777215, 8388607)
      WHEN 'INT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', 4294967295, 2147483647)
      WHEN 'BIGINT' THEN IF(c.COLUMN_TYPE LIKE '% UNSIGNED', '18446744073709551615', 9223372036854775807) # need to quote because column type defaults to unsigned.
      ELSE 0
    END > .9; # 10% buffer

Надеюсь, это поможет кому-то где-то.

person CSTobey    schedule 18.07.2017

Для MySQL 5.6 3.6.9 Использование AUTO_INCREMENT в говорит:

Используйте наименьший целочисленный тип данных для столбца AUTO_INCREMENT, который достаточно велик, чтобы вместить максимальное значение последовательности, которое вам нужно. Когда столбец достигает верхнего предела типа данных, следующая попытка создания порядкового номера завершается неудачно.

person Jingguo Yao    schedule 23.09.2015

Я хотел бы поделиться личным опытом, который у меня только что был по этому поводу. Использование Nagios + Check_MK + NDOUtils. NDOUtils хранит все проверки в таблице с именем nagios_servicechecks. Первичный ключ — это auto_increment int со знаком. Что происходит с MySQL, когда этот предел находится в диапазоне? Ну, в моем случае MySQL удаляет все записи, кроме последней. Теперь стол почти пуст. Каждый раз, когда вставляется новая запись, старая удаляется. Не знаю, почему это произошло, но дело в том, что я потерял все свои записи. IDOUtils, используемый с Icinga (не Nagios), устранил эту проблему, изменив int на bigint. Это не выдавало ошибку.

person Samuel Casimiro    schedule 26.11.2015