让我们从:
开始CREATE TABLE "houses" (
"id" serial NOT NULL PRIMARY KEY,
"name" character varying NOT NULL)
想象一下,我尝试同时(!)在一个语句中插入多个记录(可能10个可能是1000个)。
INSERT INTO houses (name) VALUES
('B6717'),
('HG120');
当单个线程在单个语句中插入X记录时(同时其他线程同时尝试将其他记录插入到同一个表中),这些记录将具有从A到A + X编号的ID,是否可以保证-1?或者是否有可能A + 100将被线程1和A + 99线程2占用?
答案 0 :(得分:1)
使用两个PgAdmin连接一次插入10000条记录似乎足以证明串行类型不能保证PostgreSQL 9.5上批处理的连续性
DO
$do$
BEGIN
FOR i IN 1..200 LOOP
EXECUTE format('INSERT INTO houses (name) VALUES %s%s;', repeat('(''a' || i || '''),', 9999), '(''a' || i || ''')');
END LOOP;
END
$do$;
以上结果导致属于两个不同批次的ID之间频繁重叠
SELECT * FROM houses WHERE id BETWEEN 34370435 AND 34370535 ORDER BY id;
34370435;"b29"
34370436;"b29"
34370437;"b29"
34370438;"a100"
34370439;"b29"
34370440;"b29"
34370441;"a100"
...
答案 1 :(得分:1)
我认为这将更难以证明,但事实证明它无法保证。
我使用ruby脚本让4个线程同时插入数千个记录,并检查单个语句创建的记录是否有间隙,并且确实存在。
Thread.new do
100.times do |u|
House.import(1000.times.map do |i|
{
tenant: "#{t}-#{u}",
name: i,
}
end)
end
end
end.each(&:join)
House.distinct.pluck(:tenant).all? do |t|
recs = House.where(
tenant: t,
).order('id').to_a
recs.first.id - recs.first.name.to_i == recs.last.id - recs.last.name.to_i
end
差距的例子:
[#<House:0x00007fd2341b5e00
id: 177002,
tenant: "0-43",
name: "0",>,
#<House:0x00007fd2341b5c48
id: 177007,
tenant: "0-43",
name: "1">,
...
正如您所看到的,在同一个INSERT语句中插入的第一行和第二行之间的GAP为5。