【问题标题】:postgresql - integer out of rangepostgresql - 超出范围的整数
【发布时间】:2014-06-19 13:49:03
【问题描述】:

我已经相应地设置了一张桌子:

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

甚至不知道从哪里开始调试这个。我没有用完磁盘空间,而且错误本身有点谨慎。

【问题讨论】:

  • 显示整个插入命令。
  • @ClodoaldoNeto 就是这样.. 复制和粘贴.. Unix 时间戳分别是 1403184512.22839641403184662.118,两者都很好,并且不会以任何方式影响结果。它们也被放置在插入 clumn 定义和值定义的开头。所以位置不是这里的问题。
  • 您的id 生成器是否有可能通过 2^31?
  • 试试select max(id) from raw。您也可以尝试将 ID 的类型从 SERIAL(4 字节有符号整数)更改为 BIGSERIAL(8 字节有符号整数)。分享和享受。
  • 无法在 PostgreSQL 9.3 上重现。 “id”列下的序列是最有可能的问题。 select currval('raw_id_seq') 返回什么? (您的序列名称可能不同;我的是 PostgreSQL 的默认名称。)

标签: postgresql


【解决方案1】:

SERIAL 列存储为 INTEGERs,最大值为 231-1。因此,在插入约 20 亿次之后,您的新 id 值将不再适合。

如果您希望在表的整个生命周期内插入这么多,请使用 BIGSERIAL(内部为 BIGINT,最多 263-1)创建它。

如果您稍后发现 SERIAL 不够大,您可以通过以下方式增加现有字段的大小:

ALTER TABLE raw ALTER COLUMN id TYPE BIGINT;

注意这里是BIGINT,而不是BIGSERIAL(如serials aren't real types)。请记住,如果您的表中实际上有 20 亿条记录,这可能需要一些时间...

【讨论】:

  • 我使用的语法是ALTER TABLE raw ALTER COLUMN id TYPE BIGINT 但我想都是一样的:)
  • @Torxed 是的,COLUMN 关键字是可选的,但它确实让事情变得更加清晰。更新了 ;)
  • alter table 在实时数据库上实际上是不可行的,实际上它重建了在整个过程中锁定它的表。
  • @Gaetano:是的,如果你很早就发现了这一点,那么你可能需要更精细的东西来避免停机(例如,添加一个由触发器维护的 id 的副本,并在填充后重命名它)。但是,如果每个插入都已经因integer out of range 错误而失败,那么您的系统并不完全“活跃”,我认为您只需要等待它...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 2013-10-12
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多