可能重复:
is there a way to avoid calling nextval() if the insert fails in PostgreSQL?
Rails - Postgres does not re-use deleted ids but MySql does?
我有一个非常简单的数据库 PostgreSQL 9.2.1 。当我使用此方法插入 Doctrine2 的内容时:
$em->persist($entity);
$em->flush();
如果我收到错误
-means记录 NOT 插入 -
它仍然将1
添加到我的主键。因此,如果我刷新页面50
次,则表示自动增量值设置为50
。我怎么能阻止这个?如果记录没有说明为什么主键增加。这非常关键,因为它只使用索引,而且数字会越来越大。
我不知道它是什么来的,为什么,所以,我没有尝试任何东西。此时非常困难。
答案 0 :(得分:5)
Doctrine2使用事务来完成它的任务。
每次Doctrine将其更改刷新到数据库时,它都会打开一个事务,每个记录都已准备好,然后提交将同时执行所有更改。
在此过程中,将分配需要auto_increment
ID的记录。如果记录在提交阶段失败,则不会添加记录,但自动增量已发出该ID。
您可以在此处详细了解交易:http://www.postgresql.org/docs/current/static/tutorial-transactions.html
注意:MySQL也是如此,我对其他许多RDBMS也一样。
答案 1 :(得分:2)
没有办法避免你观察到的行为而不会导致严重的性能损失或不正确的并发操作。
Auto-incrementing fields是通过default nextval('seqeunce_name')
将字段绑定到sequence来实现的。
序列旨在保证即使在并发操作下它们也始终发出唯一值。他们不能保证他们总是发出顺序值。当您尝试插入行时调用nextval()
时,除非您使用setval()
手动重置序列,否则将发出该值并且永远不会再次发出该值。
由于安全地递增序列必然会产生锁定开销,因此在高度并发操作下,某些dbms系统将为每个事务或会话缓存一组序列值以避免过度锁定 - 这进一步加剧了跳过的序列值问题。在postgres中,这种值的缓存是通过序列创建的CACHE cache
子句来控制的。