12

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

4

4 回答 4

21

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

也就是说,它实际上并不是“线程安全的”,因为 PostgreSQL 使用多处理模型而不是多线程模型,并且因为大多数客户端驱动程序(例如 libpq)一次不允许超过一个线程与单个连接进行交互。

您还应该知道,虽然nextval可以保证返回不同且不断增加的值,但不能保证在没有“洞”或“间隙”的情况下这样做。当生成的值被丢弃而不被提交(例如,由 a 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 无间隙序列”以获取更多信息。

于 2013-01-08T13:56:38.937 回答
2

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

否则它不会有用。

编辑:这是你如何使用 nextval 和 currval:

nextval 返回一个新的序列号,您可以将其用于第一个表的插入中的 id

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

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

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

于 2013-01-08T12:41:41.647 回答
2

是的,它是线程安全的。

手册

nextval

将序列对象推进到下一个值并返回该值。这是原子完成的:即使多个会话同时执行 nextval,每个会话都将安全地接收到不同的序列值。

(强调我的)

于 2013-01-08T12:43:07.153 回答
1

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

顺便说一句:这应该是评论,而不是答案;但我还不能发表评论。

于 2013-01-08T17:36:26.167 回答