【问题标题】:How to get the next number in a sequence for PostgreSQL如何获取 PostgreSQL 序列中的下一个数字
【发布时间】:2016-07-22 11:58:14
【问题描述】:

我正在尝试为 PostgreSQL 做 this。我了解 PostgreSQL 作家不会阻止读者。那么如何安全地增加表中的序列。我知道 PostgreSQL 有一个序列功能,但我不是在寻找这个,因为那时我会在数据库中创建数千个序列。

我有一张这样的桌子:

+----+-----------+------+-------+--+
| id | Part      | Seq  | Model |  |
+----+-----------+------+-------+--+
| 1  | Head      | 0    | 3     |  |
| 2  | Neck      | 1    | 3     |  |
| 3  | Shoulders | 2    | 29    |  |
| 4  | Shoulders | 2    | 3     |  |
| 5  | Stomach   | 5    | 3     |  |
+----+-----------+------+-------+--+

对于 Model 3,我如何在 Stomach 之后插入另一条记录,下面是新表的样子:

+----+-----------+------+-------+--+
| id | Part      | Seq  | Model |  |
+----+-----------+------+-------+--+
| 1  | Head      | 0    | 3     |  |
| 2  | Neck      | 1    | 3     |  |
| 3  | Shoulders | 2    | 29    |  |
| 4  | Shoulders | 2    | 3     |  |
| 5  | Stomach   | 5    | 3     |  |
| 6  | Groin     | 6    | 3     |  |
+----+-----------+------+-------+--+

有没有一种方法可以制作一个插入查询,它只会在 Model 3 的最高序列之后给出下一个数字。另外,寻找并发安全的东西。

【问题讨论】:

标签: sql postgresql postgresql-9.4


【解决方案1】:

您可以在插入语句中使用as 关键字查询表。您可以找到完整的语法 here,但在这种情况下,您需要的语法是 insert into <table_name> (<columns...>) <query>。

为了确保其他会话无法运行类似的查询,听起来您需要SHARE ROW EXCLUSIVE (SRE) 锁定。根据文档:

此模式可保护表免受并发数据更改的影响,并且是自排的,因此一次只能有一个会话保持它。

SRE 锁与其他 ROW EXCLUSIVE (RE) 锁发生冲突,这些锁在任何插入过程中被获取,但仍允许从表中读取。然而,RE 锁本身不会阻止其他会话同时进行插入,因此简单的插入不足以防止并发更改。

SRE 锁通常通过更改表或创建触发器自动获得,但也可以手动创建。您需要在插入之前获得锁,然后通过尽快提交更改来释放它。

例如:

begin work;
    lock table my_table in share row exclusive mode;

    insert into my_table
        (id, part, seq, model) as
    select
        max(id) + 1 as id,
        'Next Body Part' as part,
        max(seq) + 1 as seq,
        4 as model
    from
        my_table;
commit work;

需要注意的一点是,这不会阻止应用程序获取最大序列(在上述语句运行之前或期间),然后处理该序列并使用该变量创建一个新的插入语句。 (例如? as seq,绑定参数为$max_sequence + 1)。为了确保它保持并发,您需要确保在同一个插入语句中获得序列号,或者至少在应用程序具有 SRE 锁时获得。

【讨论】:

  • 有没有办法锁定特定的行?我有一张大桌子,不想锁住整张桌子。我想在行被锁定时防止读写。
  • 好吧,听起来您可能想要一个共享独占锁。我已经更新了帖子以反映它是如何工作的。您仍然可以阅读,但如果您介意最后提到的警告,您应该不会遇到并发问题。
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 2014-10-08
  • 2012-11-03
  • 1970-01-01
  • 2016-02-29
  • 2013-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多