Bizonozubr
@Bizonozubr
IT специалист в не IT сфере

Откуда появляются отрицательные значения индекса первичного ключа PostgreSQL?

Появился следующий вопрос в плане работы с PostgreSQL через Entity Framework.

Имеется следующая таблица:
CREATE TABLE "TankContentStateHistory" (
"TankContentStateHistoryId" integer NOT NULL SET DEFAULT nextval('"TankContentStateHistory_TankContentStateHistoryId_seq"'::regclass),
"AverageTemperature" double precision NOT NULL,
...
"GTVolume" double precision DEFAULT 0.0 NOT NULL);


TankContentStateHistoryId берет свои значения из перечисления TankContentStateHistory_TankContentStateHistoryId_seq:
CREATE SEQUENCE "TankContentStateHistory_TankContentStateHistoryId_seq"
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


Значения должны быть все время положительными, но в последнее время стали появляться моменты, когда первичный ключ становится с отрицательным значением и откуда оно берется - не понятно. Логи PostgreSQL ясности не вносят:
2021-09-19 00:45:58 MSK ОШИБКА:  повторяющееся значение ключа нарушает ограничение уникальности "PK_TankContentStateHistory"
2021-09-19 00:45:58 MSK ПОДРОБНОСТИ:  Ключ "("TankContentStateHistoryId")=(-2147482602)" уже существует.
2021-09-19 00:45:58 MSK ОПЕРАТОР:  INSERT INTO "TankContentStateHistory" ("TankContentStateHistoryId", ... "GTVolume")
VALUES ($1, ..)


EntityFrameworkCore по сути дублирует тоже самое:
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Npgsql.PostgresException: 23505: повторяющееся значение ключа нарушает ограничение уникальности "PK_TankContentStateHistory"
в Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext()


Вопрос в следующем - в каком месте может возникнуть проблема? Потому что после тщетных попыток уставить значение, все следующие значения ключа идет дальше по последовательности (например, id = 2044, потом отрицательное значение id=-454635, после id=2045).
  • Вопрос задан
  • 1037 просмотров
Решения вопроса 1
Пригласить эксперта
Ответы на вопрос 2
rozhnev
@rozhnev
Fullstack programmer, DBA, медленно, дорого
А почему бы не использовать встроеный тип serial вместо TankContentStateHistory_TankContentStateHistoryId_seq
CREATE TABLE "TankContentStateHistory" (
  "TankContentStateHistoryId" serial NOT NULL,
  "AverageTemperature" double precision NOT NULL,
  "GTVolume" double precision DEFAULT 0.0 NOT NULL
);

INSERT INTO "TankContentStateHistory" ("AverageTemperature", "GTVolume") VALUES (10, 20);

SELECT * FROM "TankContentStateHistory";


PostgreSQL fiddle
Ответ написан
kingleonfromafrica
@kingleonfromafrica
from Africa
Отрицательные значения признак того, что у Вас счетчик "на второй круг пошел".
Поменяйте на BigInt.

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

Войдите, чтобы написать ответ

Похожие вопросы