11

我有一个关于 SQLite 数据库的纯学术问题。

我正在使用 SQLite.net 在我的 WinForm 项目中使用数据库,并且在设置新表时,我开始考虑 ID 列的最大值。

我将IDENTITY用于我的[ID]列,根据SQLite.net DataType Mappings,它相当于DbType.Int64. 我通常从零开始我的 ID 列(将该行作为测试记录)并让数据库自动递增。

最大值 ( Int64.MaxValue) 为 9,223,372,036,854,775,807。就我的目的而言,我什至不会在达到那个最大值时触及表面,但是在数据库中会发生什么?在尝试阅读此内容时,我发现 DB2 显然将值“包装”为负值(-9,223,372,036,854,775,807)并从那里递增,直到数据库无法插入行,因为 ID 列必须是唯一的。

这是在 SQLite 和/或其他数据库引擎中发生的情况吗?

4

4 回答 4

25

我怀疑是否有人确切知道,因为如果每秒插入一百万行,则需要大约 292,471 年才能达到环绕风险点——而数据库已经存在了一小部分时间(实际上,智人也是如此;-)。

于 2009-06-13T03:12:10.840 回答
7

IDENTITY 实际上并不是在 SQLite 中自动递增的正确方法。这将需要您在应用层中进行递增。在 SQLite 外壳中,尝试:

create table bar (id IDENTITY, name VARCHAR);
insert into bar (name) values ("John");
select * from bar;

你会看到 id 只是空的。SQLite 没有赋予 IDENTITY 任何特殊意义,因此它基本上是一个普通的(无类型的)列。

另一方面,如果你这样做:

create table baz (id INTEGER PRIMARY KEY, name VARCHAR);
insert into baz (name) values ("John");
select * from baz;

正如我认为你所期望的那样,它将是 1。

请注意,还有一个 INTEGER PRIMARY KEY AUTOINCREMENT。基本区别在于 AUTOINCREMENT 确保密钥永远不会被重用。因此,如果您删除 John,则 1 将永远不会被重新用作 id。无论哪种方式,如果您使用 PRIMARY KEY(带有可选的 AUTOINCREMENT)并用完 id,则 SQLite 应该会因 SQLITE_FULL 而失败,而不是回绕。

通过使用 IDENTITY,您确实打开了(可能不相关的)如果数据库已满,您的应用程序将错误地环绕的可能性。这是很有可能的,因为 SQLite 中的 IDENTITY 列可以保存任何值(包括负整数)。再次尝试:

insert into bar VALUES ("What the hell", "Bill");
insert into bar VALUES (-9, "Mary");

这两个都是完全有效的。它们对 baz 也有效。 但是,使用 baz 可以避免手动指定 id。这样,您的 id 列中将永远不会有垃圾。

于 2009-06-13T03:25:22.527 回答
3

http://www.sqlite.org/autoinc.html上的文档表明,ROWID一旦达到最大数量,它将尝试通过随机化找到未使用的值。

因为一旦表中有最大值,AUTOINCREMENT它将SQLITE_FULL在所有尝试插入此表中失败:

如果该表之前保存了具有最大可能 ROWID 的行,则不允许新的 INSERT,并且任何插入新行的尝试都将失败并返回 SQLITE_FULL 错误。

这是必要的,因为可以AUTOINCREMENT保证 ID 单调递增。

于 2010-09-17T14:00:02.503 回答
1

我无法谈论任何特定的 DB2 实现逻辑,但您描述的“环绕”行为是通过二进制补码实现签名的数字的标准。

至于实际会发生什么,关于数据库将如何处理它完全悬而未决。问题出现在实际创建对字段来说太大的 id 的时间点,因为引擎内部不太可能使用超过 64 位的数据类型。到那时,任何人都在猜测......用于开发引擎的内部语言可能会抛出,数字可能会默默地回绕并导致主键冲突(假设存在冲突的 ID),世界可能会出现由于您的溢出等而结束

但实际上,亚历克斯是正确的。此处涉及的行数的理论限制(假设它是每行一个 id,而不是任何类型的作弊者身份插入恶作剧)基本上会使情况变得没有意义,因为当您可以想象输入那么多行时即使是惊人的插入率,无论如何我们都会死掉,所以没关系:)

于 2009-06-13T03:17:05.993 回答