postgresql — целое число вне диапазона

#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 ошибкой, значит, ваша система не совсем «живая», и я думаю, вам просто нужно переждать…