首页 > 解决方案 > PostgreSQL 序列线程上的 setval nextval 增量是否安全?

问题描述

我想在 PostgreSQL 中将一个序列增加一些 batchSize,但我不确定这个查询对于对同一序列的并发调用是否安全。

select setval('my_sequence', nextval('my_sequence') + batchSize);

鉴于上面的查询,我担心的是,setval()如果另一个线程同时获取了它,那么对序列的调用会将序列设置回来或者可能会中止查询nextval()

例如:

线程 1. nextval = 1001 batchSize = 100 将序列设置为 1101

Tread 2. nextval = 1002 batchSize = 20 将序列设置为 1022

这意味着序列最终可能会为 1002 到 1101 之间的 id 返回重复的 sequenceId。

使用该generate_series()功能也可以实现相同的目的。缺点是不能保证该系列是按顺序排列的,因为其他线程可以同时调用nextval()同一序列,这意味着我必须获取并解析生成的系列。

标签: sqlpostgresqlsequence

解决方案


来自PG 文档

为了避免阻塞从同一序列中获取数字的并发事务,nextval 操作永远不会回滚;也就是说,一旦获取了一个值,它就被认为是已使用的,并且不会再次返回。即使周围的事务稍后中止,或者调用查询最终没有使用该值也是如此。例如,带有 ON CONFLICT 子句的 INSERT 将计算要插入的元组,包括执行任何所需的 nextval 调用,然后再检测任何可能导致其遵循 ON CONFLICT 规则的冲突。这种情况会在赋值序列中留下未使用的“漏洞”。因此,PostgreSQL 序列对象不能用于获取“无间隙”序列。同样,如果事务回滚,setval 所做的任何序列状态更改都不会撤消。

我会假设上述状态是线程安全的。


推荐阅读