3

由于它可能导致的问题,这种情况发生的可能性对我来说似乎极不可能,但我想我还是会问这个问题......

想象一个涉及自动增量 ID 并分配值的事务。在 COMMIT 之前,涉及的代码会缓存分配的 ID 的副本以供以后参考。然后提交事务。

假设没有直接的客户干预(删除或更改记录),是否有任何数据库或情况会在提交后立即自动更改 ID 值,从而使缓存的 ID 不正确?在事务中缓存 ID 总是安全的吗?

我可以想象发生这种情况的一个假设情况是,如果某些 RDBMS 实现莫名其妙地决定有必要具有无间隙且与时间相关的自动增量值(因为我看到很多人想要这个的例子)。在这个假设的情况下,我可以想象可能会对 ID 进行一些神奇的洗牌,以填补由另一个事务(或其他间隙原因)中的后 ID 分配回滚引起的间隙。这将使缓存的值无效。

任何人都知道这样的实现,或其他缓存杀手?

4

2 回答 2

5

生成的 id 值的实现通常涉及在短原子操作中递增计数器值。然后,该值被请求事务使用,即使该事务将回滚,保留的值也永远不会返回到空闲值池。所以从这个角度来看,我认为所描述的情况不太可能。此外,在 pl/sql 类型的程序中,您确实需要生成正确的值才能将其他相关行插入到子表中。

至于想要按时间排序的无间隙 id 值的人:自动增量/代理键的唯一目的是为一行创建人工标识。它应该与确定创建行的顺序无关。有更好的方法可以做到这一点,例如使用创建时间戳。

于 2011-01-13T18:05:20.370 回答
1

PostgreSQL支持DEFERRED可以更改数据的触发器COMMIT

CREATE TABLE test_autoinc (id BIGSERIAL);

CREATE TABLE test_other (id BIGSERIAL);

CREATE FUNCTION prc_update_autoinc()
RETURNS TRIGGER
AS
$$
BEGIN
        UPDATE  test_autoinc
        SET     id = id + 10;
        RETURN  NEW;
END;
$$
LANGUAGE 'plpgsql';

CREATE CONSTRAINT TRIGGER
        trg_other_ai
AFTER INSERT
ON      test_other
DEFERRABLE
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE prc_update_autoinc();

BEGIN TRANSACTION;

INSERT
INTO    test_autoinc
DEFAULT VALUES;

INSERT
INTO    test_other
DEFAULT VALUES;

SELECT  *
FROM    test_autoinc;

COMMIT;

SELECT  *
FROM    test_autoinc;

第一个SELECT(在 之前COMMIT)返回1,第二个(在 之后COMMIT)返回11

于 2011-01-13T16:29:40.387 回答