我正在为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 | |
+----+-----------+------+-------+--+
如何为模型3的Stomach
之后的下一个seq插入另一条记录。所以这是新表假设的样子:
+----+-----------+------+-------+--+
| 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 | |
+----+-----------+------+-------+--+
有没有办法制作一个插入查询,它只会在模型3的最高seq之后给出下一个数字。此外,寻找并发安全的东西。
答案 0 :(得分:1)
您可以使用as
关键字在insert语句中查询表。您可以找到完整语法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;
需要注意的一点是,这不会阻止应用程序获取最大序列(在上述语句运行之前或同时),然后处理该命令并使用该变量创建新的insert语句。 (例如? as seq
,绑定参数为$max_sequence + 1
)。为确保它保持并发,您需要确保在同一个insert语句中获取序列号,或者至少在应用程序具有SRE锁定时获取序列号。