Postgresql Postgres基于所有者/外键在一个表中显示唯一序列

Postgresql Postgres基于所有者/外键在一个表中显示唯一序列,postgresql,Postgresql,我正在创建一个web应用程序,它将使用权限、角色和FK限制数据访问,将所有用户信息存储在一个数据库中。此应用程序中的一个表跟踪每个用户创建的工单(即工单表对用户表具有FK) 我希望确保每个用户都有自己的“工单ID”不间断序列,这些ID是在安排工单时分配的。也就是说,如果用户1创建了他的第一个工单,它将为其分配#1,但是,如果用户2创建了他的第五个工单,它将为其分配#5 工单表有一个UUID主键,因此每个记录都是可区分的,并且用户FK有一个NOTNULL约束 根据我目前的研究,似乎Postgres

我正在创建一个web应用程序,它将使用权限、角色和FK限制数据访问,将所有用户信息存储在一个数据库中。此应用程序中的一个表跟踪每个用户创建的工单(即工单表对用户表具有FK)

我希望确保每个用户都有自己的“工单ID”不间断序列,这些ID是在安排工单时分配的。也就是说,如果用户1创建了他的第一个工单,它将为其分配#1,但是,如果用户2创建了他的第五个工单,它将为其分配#5

工单表有一个UUID主键,因此每个记录都是可区分的,并且用户FK有一个NOTNULL约束

根据我目前的研究,似乎Postgres序列可能是我最好的答案。我需要为每个用户创建一个序列,并将其合并到触发器中,以在工单记录上加盖下一个适当的ID。然而,这似乎需要非常高的性能,并且为每个用户创建一个新序列将有其自身的挑战

第二种方法是创建第二个表,跟踪每个用户的最新序列,查询它,增加它,并更新工单表和编号跟踪表。然而,在这种情况下,我认为如果两个用户同时转换记录,那么很容易受到竞争条件的影响


我不确定解决这个问题的最好办法是什么。还有其他方法可以提供更好的性能吗?

序列对您不起作用,因为它们在设计上不是事务性的:如果生成了一个数字的插入失败,即使在
回滚之后,该数字也会被消耗掉

您应该创建第二个表

CREATE TABLE counters (
   user_id bigint PRIMARY KEY REFERENCES users ON DELETE CASCADE,
   work_order_id bigint NOT NULL DEFAULT 0
);
然后你就可以用

UPDATE counters
SET work_order_id = work_order_id + 1
RETURNING work_order_id;
这是原子的,不受种族条件的影响。只要确保在同一个数据库事务中运行更新和插入,它们要么都会成功,要么都会失败并被撤消


这将为每个用户将插入序列化到工作订单表中,但无间隙序列始终是一个性能问题。

感谢您的反馈!这是在客户端实现并进行2次调用(第一次是ID检索,第二次是使用新ID保存记录)还是在服务器端实现以确保没有失败的调用更好?我在答案中添加了一句话。您必须在同一事务中运行更新和插入,如果出现问题,则两者都将回滚。正如@Laurenz指出的,保持无间隔序列始终是一个性能问题,而且往往会成为维护的噩梦。更好的解决方案是放弃它,只创建一个序列供所有用户使用。通常,保持一个无间隔的序列是不值得付出努力的。问问自己这样做的商业重要性是什么?如果您的应用程序中需要按用户顺序订购,则可通过时间戳或/和报复性顺序获取。“只是IMHO!”Belayer,我也对无间隙序列的概念提出了质疑,但由于这些将被过账的会计文件,所以在编号上不能有任何间隙。如果存在漏洞,他们可能会面临审计问题。