Yandex Metrika
sanches.free 1 просмотр

Ошибка Duplicate entry для PRIMARY: когда заканчивается INT у свойств инфоблока

Симптом

Частый сценарий: массовое обновление значений свойств или штатные операции ядра с таблицами вида b_iblock_element_prop_mNN завершаются ошибкой вставки. В хвосте сообщения MySQL фигурирует Duplicate entry '2147483647' for key 'PRIMARY'. Число 2147483647 — это верхняя граница 32-битного знакового целого; дальше автоинкремент «хочет» выдать то же значение, что уже занято первичным ключом, и движок отклоняет строку.

Почему так бывает в Битрикс

Для многозначных и сложных свойств инфоблока ядро создаёт отдельные таблицы свойств. Первичный ключ там обычно объявлен как INT(11) NOT NULL AUTO_INCREMENT без UNSIGNED. Каждое сохранение значения отъедает новый ID, причём при частых пересохранениях и обменах счётчик растёт быстрее, чем кажется по числу «живых» строк в таблице. В итоге AUTO_INCREMENT подходит к 2147483647, хотя фактических записей может быть существенно меньше.

Быстрая проверка схемы

Убедитесь, что речь именно о исчерпании диапазона, а не о логической коллизии первичного ключа из-за ручных вставок:

SHOW CREATE TABLE b_iblock_element_prop_m45\G

Обратите внимание на строку AUTO_INCREMENT=... рядом с определением ID. Если там уже максимум для знакового INT, дальнейшие вставки будут стабильно падать до смены типа или перенумерации.

Вариант 1: перевести ключ в UNSIGNED

Переход на INT UNSIGNED увеличивает доступный положительный диапазон примерно вдвое (до 4294967295) при той же ширине типа. На проектах, где не ожидают лавины новых идентификаторов, этого хватает на годы. Типовой шаг (после бэкапа и на копии БД!):

ALTER TABLE `b_iblock_element_prop_m45`
  MODIFY `ID` INT UNSIGNED NOT NULL AUTO_INCREMENT;

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

Вариант 2: перенумерация и зависимости

Если нужно «отодвинуть» потолок надолго или не хотите трогать тип, можно сжать идентификаторы: фактическое число строк меньше текущего максимума ID, значит есть запас для новой монотонной нумерации. Сложность в том, что на пару к b_iblock_element_prop_mNN часто существует таблица b_iblock_element_prop_sNN, где связи многозначных свойств могут храниться в сериализованном PHP-представлении — там внутри строк лежат старые числовые ID как текст, и «чистый» одношаговый UPDATE по SQL не найдёт все вхождения.

Рабочий порядок на практике такой: сделать точечный дамп проблемной пары таблиц, зафиксировать выборку минимальных и максимальных ID, найти внешние упоминания этих значений (в т. ч. через поиск по дампам или по содержимому b_iblock_element_prop_sNN), затем выполнить перенос во временные таблицы и обратную подстановку с картой соответствия «старый id → новый id». Готовые утилиты для перенумерации первичных ключей в экосистеме Битрикс существуют; выбирайте проверенный сценарий под свою версию ядра и обязательно прогоняйте его сначала на копии базы с контрольными выборками по затронутым элементам инфоблока.

Что зафиксировать после исправления

  • Мониторинг AUTO_INCREMENT по крупным таблицам свойств — раз в квартал достаточно для спокойных проектов.
  • Документирование изменения схемы (изменение типа или скрипт перенумерации), чтобы при миграциях и обновлениях не потерять правку.
  • При планировании очень долгоживущих каталогов с пересчётами свойств имеет смысл заранее оценивать запас по ID или рассматривать BIGINT для новых кастомных сущностей — ядро исторически опирается на INT, поэтому точечные правки таблиц свойств остаются типичным компромиссом.

Итог

Сообщение о дубликате на значении 2147483647 почти всегда указывает на исчерпание знакового 32-битного автоинкремента. Быстрый путь — UNSIGNED после бэкапа; fundamental — перенумерация с учётом сериализованных ссылок в «сестринских» таблицах свойств. Оба подхода требуют стенда и проверки бизнес-сценариев, но позволяют вернуть штатное сохранение свойств без правок прикладного PHP.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии