【问题标题】:Will unique RIDs ever "overflow"?唯一的 RID 会“溢出”吗?
【发布时间】:2010-12-30 22:08:44
【问题描述】:

我正在制作一个可以在 SQL Server 和 PostgreSQL 上运行的应用程序,所以我要问这个关于它们的问题。

当您创建一个唯一的主键(使用序列或自动增量类型的东西)并点击超过 40 亿条记录(32 位)时会发生什么?我并不是说我们的表将有 40 亿条记录,而是说已经创建了 40 亿条记录,因为 RID 只会增加。所以即使我删除了 39 亿条记录,我的 RID 仍然在 40 亿条范围内。那么会发生什么?它是把精度提高到 64 位还是翻转到 0 或者只是吐出一个非常严重的错误?我是否应该担心即使是 64 位 RID 也可能最终溢出?

另外,我该如何解决这个问题? 是否有某种清理选项或工具?我是否只需要每年创建自己的东西或完全重建表以获得一致的 RID? (因此也触及了许多使用这些 RID 的其他表是外键)

【问题讨论】:

  • 是的,32 位自动增量值会溢出。 *.com/questions/261815/…
  • 在我的一生中?还是大约10年?当数据库充满非常关键的数据时,我绝对不想在 10 年内修复这个错误
  • 在你的一生中。 2^64 = 1.8 x 10^19 行,即 1800 万行。您会在 100 万年内每年创建超过 18 万亿行吗?
  • 嗯.. 好点.. 出于某种原因,我一直认为 64 位更接近 48 位.. 哈哈
  • 你至少可以捍卫这样的假设,即 64 位对于你的新机器人霸主来说在奇点之后就足够了。

标签: sql-server postgresql scalability rowid


【解决方案1】:

在 SQL Server 上:这取决于 RID 列的类型。内部 IDENTITY 可以递增,但无法分配给 stoarge 列:

CREATE TABLE [t1] (
[tid] int IDENTITY (2147483647, 1) NOT NULL
  , name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')

这会触发错误:

Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.

但是具有足够存储空间的数字列会很好地增加:

CREATE TABLE [t1] (
[tid] numeric(38,0) IDENTITY (2147483647, 1) NOT NULL
  , name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')

类似地,一个 bigint 将在 2^^63-1 处溢出:

CREATE TABLE [t1] (
[tid] bigint IDENTITY (9223372036854775807, 1) NOT NULL
  , name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')

但是具有足够存储空间的数字列会成功:

CREATE TABLE [t1] (
[tid] numeric(38,0) IDENTITY (9223372036854775807, 1) NOT NULL
  , name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')

【讨论】:

    【解决方案2】:

    默认情况下,PostgreSQL 会出错而不是溢出:

    # create sequence willyouwrap;
    CREATE SEQUENCE
    # select setval('willyouwrap', 9223372036854775807);
           setval        
    ---------------------
     9223372036854775807
    (1 row)
    # select nextval('willyouwrap');
    ERROR:  nextval: reached maximum value of sequence "willyouwrap" (9223372036854775807)
    

    来自文档:

    序列基于 bigint 算法,因此范围不能超过 8 字节整数的范围(-9223372036854775808 到 9223372036854775807)。在一些较旧的平台上,编译器可能不支持 8 字节整数,在这种情况下,序列使用常规整数算术(范围 -2147483648 到 +2147483647)。

    但是,你可以让它循环:

    当升序或降序序列分别达到最大值或最小值时,CYCLE 选项允许序列回绕。如果达到限制,则生成的下一个数字将分别是最小值或最大值。

    如果指定了 NO CYCLE,则在序列达到最大值后对 nextval 的任何调用都将返回错误。如果没有指定 CYCLE 或 NO CYCLE,则默认为 NO CYCLE。

    不要与之抗争。花费额外的字节并保持简单。与拥有更大的键空间相比,您更有可能后悔添加额外的复杂层和/或维护任务。

    【讨论】:

      最近更新 更多