PostgreSQL:在苛刻的多用户环境中使用SELECT nextval生成器是线程安全的



我的意思是像成千上万的用户在时间更新数据库中的值?

是的,在多个并发操作的事务中使用nextval是安全的。这就是它存在的目的和理由。

也就是说,它实际上不是"线程安全"的,因为PostgreSQL使用多处理模型而不是多线程模型,而且因为大多数客户端驱动(例如libpq)不允许同时有多个线程与单个连接交互。

您还应该意识到,虽然nextval保证返回不同且递增的值,但不能保证在没有"洞"或"间隙"的情况下这样做。当生成的值在没有提交的情况下被丢弃时(例如,通过ROLLBACK),以及当PostgreSQL在服务器崩溃后恢复时,就会产生这样的间隙。

虽然nextval将始终返回递增的数字,但这并不意味着您的事务将按照它们从给定序列中获得id的顺序提交。因此,发生这样的事情是非常正常的:

Start IDs in table: [1 2 3 4]
1st tx gets ID 5 from nextval()
2nd tx gets ID 6 from nextval()
2nd tx commits:     [1 2 3 4 6]
1st tx commits:     [1 2 3 4 5 6]

换句话说,洞可以出现也可以消失。

这两个异常都是必要的和不可避免的结果,使一个nextval调用不阻塞另一个。

如果您想要一个没有这种排序和间隙异常的序列,您需要使用无间隙序列设计,它一次只允许一个事务具有未提交的生成ID,从而有效地消除该表中插入的所有并发性。这通常在计数器表上使用SELECT FOR UPDATEUPDATE ... RETURNING来实现。

搜索"PostgreSQL gap - pless sequence"获取更多信息

是线程安全的。

从手册:

nextval

将序列对象移动到下一个值并返回该值。这是自动完成的:即使多个会话并发执行nextval,每个会话也会安全地接收到不同的序列值。

(强调我的)

是:http://www.postgresql.org/docs/current/static/functions-sequence.html

否则就没有用了。

编辑:下面是如何使用nextval和curval:

nextval返回一个新的序列号,您使用它作为第一个表上插入的id

currval返回该会话获得的最后一个序列号,您可以在外键中使用它来引用第一个表

每次调用nextval都会返回另一个值,不要在同一组insert中调用它两次。

当然,您应该在任何多用户代码中使用事务。

这个海报对同样有缺陷的代码问了一个不同的问题。这里的重点是:他似乎不知道外键是如何工作的,并且把它们颠倒了(一个作为外键的序列有点尴尬)

BTW:这应该是一个评论,而不是一个答案;

相关内容

  • 没有找到相关文章

最新更新