Firebird 2.1 生成器增加值不止一个问题

问题描述 投票:0回答:1

我有一个 Firebird 生成器的问题,即使我使用

GEN_ID
函数调用它并且将 1 作为增量值调用它,该生成器也会递增超过 1,该生成器在一个存储过程中使用,并且它跟随在另一个存储过程中递增的生成器同样的方式,但是和加一是一致的,这里是存储过程的核心:

create procedure insert_proc (
    Type integer)
returns (
    Op1 integer,
    Op2 integer)
as
begin

if (:Type = 0) then
begin
  Op1 = GEN_ID(GEN_OP1, 1);
  Op2 = GEN_ID(GEN_OP2, 1);
END

Insert Into Table1(Op1, Op2) VALUES(:Op1, :Op2);

end

该生成器唯一递增 1 的地方是此存储过程与第一个生成器相同,第一个生成器始终递增 1,但第二个生成器有时会使用除示例 6 或 3 以外的值递增。

此过程在同一事务的上下文中调用并正确提交,因为第一个生成器始终是顺序的,但第二个生成器有时会因变量值而关闭。

我还没有尝试任何东西,因为代码是正确的,但似乎我必须缺少一些有关事务级别的信息,或者它可能与数据库或Firebird服务器的版本有关,这就是为什么我需要一些这里有专业知识。

concurrency transactions generator firebird
1个回答
0
投票

Firebird 生成器不受事务控制,并且存储过程不是原子操作。这意味着如果另一个连接或另一个事务也增加了生成器(例如通过调用相同的存储过程),则可以交错生成值。

也就是说,对于两个事务 T1 和 T2,可能存在多种操作顺序:

T1: Op1 = GEN_ID(GEN_OP1, 1); (T1:OP1 = 1)
T1: Op2 = GEN_ID(GEN_OP2, 1); (T1:OP2 = 1)
T2: Op1 = GEN_ID(GEN_OP1, 1); (T2:OP1 = 2)
T2: Op2 = GEN_ID(GEN_OP2, 1); (T2:OP2 = 2)
T1: Op1 = GEN_ID(GEN_OP1, 1); (T1:OP1 = 1)
T2: Op1 = GEN_ID(GEN_OP1, 1); (T2:OP1 = 2)
T1: Op2 = GEN_ID(GEN_OP2, 1); (T1:OP2 = 1)
T2: Op2 = GEN_ID(GEN_OP2, 1); (T2:OP2 = 2)
T1: Op1 = GEN_ID(GEN_OP1, 1); (T1:OP1 = 1)
T2: Op1 = GEN_ID(GEN_OP1, 1); (T2:OP1 = 2)
T2: Op2 = GEN_ID(GEN_OP2, 1); (T2:OP2 = 1)
T1: Op2 = GEN_ID(GEN_OP2, 1); (T1:OP2 = 2)
T2: Op1 = GEN_ID(GEN_OP1, 1); (T2:OP1 = 1)
T1: Op1 = GEN_ID(GEN_OP1, 1); (T1:OP1 = 2)
T2: Op2 = GEN_ID(GEN_OP2, 1); (T2:OP2 = 1)
T1: Op2 = GEN_ID(GEN_OP2, 1); (T1:OP2 = 2)
T2: Op1 = GEN_ID(GEN_OP1, 1); (T2:OP1 = 1)
T2: Op2 = GEN_ID(GEN_OP2, 1); (T2:OP2 = 1)
T1: Op1 = GEN_ID(GEN_OP1, 1); (T1:OP1 = 2)
T1: Op2 = GEN_ID(GEN_OP2, 1); (T1:OP2 = 2)

中间的示例,订单 T1,T2,T2,T1,是为 T1 引入间隙的示例。添加更多并发事务,可能的组合会爆炸,差异可能会增加。

对此没有真正的解决方案,除了您不应该关心它之外,或者您应该始终使用单个生成器,将其增加 2,并将返回值用于一列,并返回值 - 1另一个(但这可能会对您的数据模型产生其他影响,并且基本上表明您不需要两列,只需一列就足够了,所以我不建议这样做)。

© www.soinside.com 2019 - 2024. All rights reserved.