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

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

Но что происходит, когда я получаю более 2 (или 4) миллиардов постов, а целого недостаточно? Целое число переполнено и продолжается или выброшено исключение, которое я могу обработать?

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

6 ответов

Решение

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

На случай, если возникнут какие-либо вопросы, поле AUTO_INCREMENT / НЕ ОБРАЩАЕТСЯ /. Как только вы достигнете предела размера поля, INSERT генерирует ошибку. (Согласно Джереми Коулу)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам