我的意思是像成千上万的用户在时间更新数据库中的值?
是的,在多个并发操作的事务中使用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 UPDATE
或UPDATE ... 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:这应该是一个评论,而不是一个答案;