'安全'在重载时插入导致PK违规

时间:2018-02-07 23:55:00

标签: sql postgresql insert race-condition postgresql-9.4

我在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 ......

1 个答案:

答案 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命令都不会自动获取此锁定模式。

此解决方案允许在保持锁定时读取并将写入写入等待列表。