🛠️ В таблице далеко не два миллиарда строк, а INSERT уже не получает новый ID
Причина может быть не в количестве строк.
А в sequence.
Sequence — не счётчик сохранённых записей. Она выдаёт значения.
Если nextval() вернул номер, а транзакция потом откатилась, значение не возвращается обратно.
Поэтому:
count(*)
MAX(id)
last_value
могут различаться.
Что может расходовать sequence:
— rollback после nextval();
— конфликтующая вставка;
— прямой вызов nextval();
— CACHE;
— другие потребители sequence.
Gaps сами по себе не означают проблему.
Проблема начинается, когда генератор приближается к пределу.
С чего начать:
SELECT pg_get_serial_sequence('public.orders', 'id');
Затем параметры sequence:
SELECT
schemaname,
sequencename,
data_type,
max_value,
increment_by,
cycle,
cache_size,
last_value
FROM pg_sequences
WHERE schemaname = 'public'
AND sequencename = 'orders_id_seq';
И данные таблицы:
SELECT max(id), count(*)
FROM public.orders;
Важно: last_value — не точный следующий ID. При cache он может быть больше последнего реально выданного значения, а иногда может быть NULL.
Проверяйте оба предела:
тип ID-колонки
и
MAXVALUE sequence
Расширить integer до bigint недостаточно, если sequence осталась со старым пределом. Менять только sequence тоже бессмысленно, если колонка не принимает новый диапазон.
При NO CYCLE после исчерпания диапазона следующий nextval() завершится ошибкой.
CYCLE для PK — опасный вариант: sequence может вернуться к уже существующим ID и получить конфликт уникальности.
Главная ошибка — считать MAX(id) реальным показателем остатка sequence.
Сохраните проверку, которую стоит добавить для старых таблиц с постоянно растущим ID.
🔹🔹🔹🔹
Причина может быть не в количестве строк.
А в sequence.
Sequence — не счётчик сохранённых записей. Она выдаёт значения.
Если nextval() вернул номер, а транзакция потом откатилась, значение не возвращается обратно.
Поэтому:
count(*)
MAX(id)
last_value
могут различаться.
Что может расходовать sequence:
— rollback после nextval();
— конфликтующая вставка;
— прямой вызов nextval();
— CACHE;
— другие потребители sequence.
Gaps сами по себе не означают проблему.
Проблема начинается, когда генератор приближается к пределу.
С чего начать:
SELECT pg_get_serial_sequence('public.orders', 'id');
Затем параметры sequence:
SELECT
schemaname,
sequencename,
data_type,
max_value,
increment_by,
cycle,
cache_size,
last_value
FROM pg_sequences
WHERE schemaname = 'public'
AND sequencename = 'orders_id_seq';
И данные таблицы:
SELECT max(id), count(*)
FROM public.orders;
Важно: last_value — не точный следующий ID. При cache он может быть больше последнего реально выданного значения, а иногда может быть NULL.
Проверяйте оба предела:
тип ID-колонки
и
MAXVALUE sequence
Расширить integer до bigint недостаточно, если sequence осталась со старым пределом. Менять только sequence тоже бессмысленно, если колонка не принимает новый диапазон.
При NO CYCLE после исчерпания диапазона следующий nextval() завершится ошибкой.
CYCLE для PK — опасный вариант: sequence может вернуться к уже существующим ID и получить конфликт уникальности.
Главная ошибка — считать MAX(id) реальным показателем остатка sequence.
Сохраните проверку, которую стоит добавить для старых таблиц с постоянно растущим ID.
🔹🔹🔹🔹