我在将Firebird 2.5与FlameRobin结合使用时,昨天在使用以下SQL创建简单序列/生成器时遇到了一个奇怪的问题:

CREATE GENERATOR MY_GEN_NAME_HERE;


这给出了以下错误消息:

Error: *** IBPP::SQLException ***
Context: Statement::Execute( CREATE GENERATOR MY_GEN_NAME_HERE)
Message: isc_dsql_execute2 failed

SQL Message : -607
This operation is not defined for system tables.

Engine Code    : 335544351
Engine Message :
unsuccessful metadata update
DEFINE GENERATOR failed
arithmetic exception, numeric overflow, or string truncation
numeric value is out of range
At trigger 'RDB$TRIGGER_6'


根据Firebird FAQ,这意味着已达到数据库中的最大生成器数。该数据库仅包含约250个实际生成器,并且根据the manual,应该有32767个可用。

常见问题解答建议备份和还原可以解决该问题,并且确实可以解决此问题,但是理想情况下,我想了解为什么会这样,以便下次可以避免。

我知道,即使创建失败的生成器也可以增加计数器,所以我相信这一定是问题所在。由于数据库尚未在生产中使用,因此“手动”生成器创建语句失败的可能性很小,而且我们中只有两个人正在使用该数据库进行开发。我认为这一定是试图以编程方式创建生成器的事情,尽管据我所知,我们编写的任何内容都不应这样做。我不能排除我们正在与数据库一起使用的行业ERP系统,并且已经向供应商提出了该建议,但无论是哪种情况,我都会感到非常惊讶。

以前有没有人遇到过这个问题,还有其他可能影响生成器计数器的问题吗?

最佳答案

序列(生成器)在生成器数据页面上具有一个“槽”,用于存储其当前值。创建生成器时(使用内部序列)分配此插槽号(RDB$GENERATOR_ID)。

删除序列时,插槽编号只会增加,直到已分配(并可能已删除)最大插槽数量为止。

在Firebird 2.1和更早版本中,这将是结束:创建(并删除)32757序列将意味着您无法再创建序列。因此,如果您的应用程序正在创建(删除)许多序列,那么即使您只有250个“实时”序列,您最终也会用尽插槽。

回收这些插槽的唯一方法是备份和还原数据库。在还原期间,将重新创建序列(使用备份中的起始值)并分配一个新的插槽。这些插槽将被连续分配,因此以前存在的间隙将消失,然后您将拥有未分配的插槽。

但是,已使用CORE-1544更改了Firebird 2.5,Firebird现在将自动回收未使用的插槽。此更改仅适用于ODS 11.2或更高版本的数据库(ODS =磁盘结构)。 ODS 11.2是使用Firebird 2.5创建的数据库的磁盘结构。

如果收到此错误,则您的数据库可能仍然是(以前)ODS 11.1(Firebird 2.1磁盘结构)或更早的版本。 Firebird 2.5可以读取早期的磁盘结构。升级数据库的ODS是备份和还原数据库的问题。鉴于您已经这样做了,我假设您的数据库现在是ODS 11.2,并且应该不再发生该错误(除非您的数据库中实际上有32767个序列)。

08-04 10:17
查看更多