#postgresql
#postgresql
Вопрос:
Я соответствующим образом настроил таблицу:
CREATE TABLE raw (
id SERIAL,
regtime float NOT NULL,
time float NOT NULL,
source varchar(15),
sourceport INTEGER,
destination varchar(15),
destport INTEGER,
blocked boolean
); ... index and grants
Я уже некоторое время успешно использую эту таблицу, и внезапно следующая вставка больше не работает..
INSERT INTO raw(
time, regtime, blocked, destport, sourceport, source, destination
) VALUES (
1403184512.2283964, 1403184662.118, False, 2, 3, '192.168.0.1', '192.168.0.2'
);
Ошибка: ERROR: integer out of range
Даже не уверен, с чего начать отладку этого.. У меня нет свободного места на диске, и сама ошибка довольно незаметна.
Комментарии:
1. Показать всю команду insert.
2. @ClodoaldoNeto вот и все .. скопируйте и вставьте.. Временная метка Unix
1403184512.2283964
и1403184662.118
, соответственно, оба в порядке и никак не влияют на результат, что когда-либо. Кроме того, они помещаются в начало как определений групп insert, так и определений значений. Таким образом, позиция здесь не проблема.3. Есть ли вероятность, что ваш
id
генератор передал 2 ^ 31?4. Попробуйте
select max(id) from raw
. Вы также можете попробовать изменить тип идентификатора с SERIAL (целое число со знаком 4 байта) на BIGSERIAL (целое число со знаком 8 байт). Делитесь и наслаждайтесь.5. Не удается воспроизвести в PostgreSQL 9.3. Последовательность, лежащая в основе столбца «id», является наиболее вероятной проблемой. Что
select currval('raw_id_seq')
возвращает? (Имя вашей последовательности может отличаться; мое значение по умолчанию PostgreSQL.)
Ответ №1:
SERIAL
столбцы хранятся как INTEGER
s, что дает им максимальное значение 2 31-1. Итак, после ~ 2 миллиардов вставок ваши новые id
значения больше не будут соответствовать.
Если вы ожидаете такого количества вставок в течение срока службы вашей таблицы, создайте ее с помощью a BIGSERIAL
(внутренне a BIGINT
, максимум 2 63-1).
Если позже вы обнаружите, что a SERIAL
недостаточно велико, вы можете увеличить размер существующего поля с помощью:
ALTER TABLE raw ALTER COLUMN id TYPE BIGINT;
Обратите внимание, что оно BIGINT
здесь, а не BIGSERIAL
(поскольку сериалы не являются реальными типами). И имейте в виду, что, если у вас на самом деле есть 2 миллиарда записей в вашей таблице, это может занять некоторое время…
Комментарии:
1. Синтаксис, который я использовал, был
ALTER TABLE raw ALTER COLUMN id TYPE BIGINT
, но я думаю, это все то же самое 🙂2. @Torxed Да,
COLUMN
ключевое слово необязательно, но оно немного проясняет ситуацию. Обновлено 😉3. Таблица alter практически не выполнима в живой базе данных, действительно, она перестраивает таблицу, блокируя ее на все время.
4. @Gaetano: Верно, если вы поймали это раньше, вам может понадобиться что-то более сложное, чтобы избежать простоев (например, добавьте дубликат, поддерживаемый триггером
id
, и переименуйте его после его заполнения). Но если каждая вставка уже завершаетсяinteger out of range
ошибкой, значит, ваша система не совсем «живая», и я думаю, вам просто нужно переждать…