我在Postgresql 9.4上处理一个大的分区表(大约0.5 TB和5 x10 ^ 9行...)。这个表每天增长8 x10 ^ 6行,并且面对繁重的读/写使用。
我需要填补部分插入可能发生的缺失分钟的空白。我使用以下查询执行此操作:
INSERT INTO huge_partitioned_table(id, date_gmt, date_local)
SELECT
to_do.id AS id,
seq.seq AT TIME ZONE to_do.tz_lib AT TIME ZONE 'UTC' AS date_gmt,
seq.seq AS date_local
FROM to_do
CROSS JOIN LATERAL
generate_series(
to_do.date_needed::timestamp,
to_do.date_needed::timestamp + INTERVAL '1439 minutes',
INTERVAL '1 minute'
) seq
WHERE NOT EXISTS(
SELECT 1
FROM huge_partitioned_table hpt
WHERE
to_do.id = hpt.id
AND date_gmt = hpt.date_gmt
)
;
但这是我第二次在我的PK(id, date_gmt)
上遇到 PK违规,因为在查询运行的同时完成了缺少分钟的插入。
在这种情况下,有没有办法避免PK违规? (第9页的on duplicate key do nothing
将非常合适,但我们无法为此更新)
规则忽略每个duplicate key
的解决方案也不是很好,因为使用时区意味着我们做了一些真正的错误,并希望在那时达到PK FAIL ......
答案 0 :(得分:0)
好的,经过一些测试后,我会在桌面上找到explicit table write lock:
LOCK TABLE huge_partitioned_table IN SHARE ROW EXCLUSIVE MODE;
SHARE ROW EXCLUSIVE
与ROW EXCLUSIVE,SHARE UPDATE EXCLUSIVE,SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE和ACCESS EXCLUSIVE锁定模式冲突。这个 模式保护表免受并发数据更改,并且是 自我排斥,以便一次只能举行一次会议。
任何PostgreSQL命令都不会自动获取此锁定模式。
此解决方案允许在保持锁定时读取并将写入写入等待列表。