postgresql - psql upsert 导致 id 不连续
问题描述
我有一个带有 primary_keyid
和唯一键的 postgresql (>9.5) 表col
。当我使用
INSERT INTO table_a (col) VLUES('xxx') ON CONFLICT(col) DO NOTHING;
要执行 upsert,假设1
生成了一个带有 id 的行。
2
如果我再次运行sql,什么都不会发生,但实际上会生成并放弃id 。
然后,如果我插入一条新记录,例如,
INSERT INTO table_a (col) VLUES('yyy') ON CONFLICT(col) DO NOTHING;
3
将生成另一行带有 id的行,并且 id2
被浪费了!
有没有办法避免这种浪费?
解决方案
大概id
是一个serial
。在引擎盖下,这会导致nextval()
来自序列的调用。一个号码nextval()
一旦被退回,将永远不会再被退回。并且调用nextval()
发生在检查可能的冲突之前。
nextval
(...)
重要:为了避免阻塞从相同序列中获取数字的并发事务,
nextval
操作永远不会回滚;也就是说,一旦获取了一个值,它就被认为是已使用的,并且不会再次返回。即使周围的事务稍后中止,或者调用查询最终没有使用该值也是如此。例如,一个INSERT
withON CONFLICT
子句将计算要插入的元组,包括执行任何必需的nextval
调用,然后再检测任何可能导致它遵循ON CONFLICT
规则的冲突。这种情况会在赋值序列中留下未使用的“漏洞”。因此,PostgreSQL 序列对象不能用于获得“无间隙”序列。
得出的结论是,您的问题的答案是否定的,除非您以某种方式自己生成值,否则无法避免这种情况。
推荐阅读
- android - android studio3.x 的问题:构建项目失败
- youtube-iframe-api - Youtube iframe 设置是否已更改?
- c - 来自 PostgreSQL 中 C 扩展的“CREATE SCHEMA foo ...”查询(使用 SPI_execute_with_args)
- javascript - 如何限制调用我的函数 2 次
- python-3.x - 在 Python3 的 for 循环中将一个函数的 2 个单独的返回值附加到 2 个单独的列表中
- reactjs - 如何在 React 中使用 Material UI 组件
- kubernetes-helm - 修改 Kubernetes Helm 模板外部范围内的变量
- database - 当我访问模型文件夹中的自定义方法时收到 401 错误
- python - 关键错误:0,数据帧从另一个数据帧过滤
- apostrophe-cms - ApostropheCMS - 从用户组来宾中删除页面菜单