序列不受交易影响?

Ear*_*rlz 28 postgresql transactions rollback database-sequence

我有一张桌子

create table testtable(
  testtable_rid serial not null,
  data integer not null,
  constraint pk_testtable primary key(testtable_rid)
);
Run Code Online (Sandbox Code Playgroud)

所以我要说这个代码约20次:

begin;
insert into testtable (data) values (0);
rollback;
Run Code Online (Sandbox Code Playgroud)

然后我做

begin;
insert into testtable (data) values (0);
commit;
Run Code Online (Sandbox Code Playgroud)

最后一个

select * from testtable
Run Code Online (Sandbox Code Playgroud)
Result:
row0: testtable_rid=21 | data=0
Expected result:
row0: testtable_rid=1 | data=0

如您所见,序列似乎不受事务回滚的影响.它们继续递增,就好像提交了事务一样,然后删除了该行.有没有办法防止序列以这种方式表现?

Aar*_*ron 40

回滚序列不是一个好主意.想象一下,两个事务同时发生,每个事务都使用序列作为唯一ID.如果第二个事务提交并且第一个事务回滚,则第二个事务插入一行"2",而第一个事务将序列回滚到"1".

如果再次使用该序列,则序列的值将变为"2",这可能导致唯一约束问题.

  • 如果第二个事务提交,则此事务应该获得序列号1.由于第一个事务回滚,因此第一个事务不会采用序列号.当然,PostgreSQL没有实现那个,既不是Oracle,也不是imho,没有对事务排序的概念约束,只有实现中的约束. (4认同)
  • @HartmutP。你错了。限制是使用序列来生成唯一编号**无需扫描任何数据结构来确定该编号是否正在使用**。在不扫描的情况下确保唯一性的唯一方法是在第一次获取值时丢弃值,即使获取它们的事务未提交。 (4认同)
  • 这取决于事务隔离级别。您已经解释过,[可序列化隔离](https://www.postgresql.org/docs/11/transaction-iso.html#XACT-SERIALIZABLE)将防止出现此问题。 (2认同)

Luk*_*ský 5

不,没有.请参阅本页底部的注释.无论如何做这样的事情是个坏主意.如果有两个事务同时运行,每个事务插入一行,则希望它们插入具有不同ID的行.