是不是PostgreSQL单个查询执行原子?

时间:2015-09-21 17:04:57

标签: postgresql

在我的postgresql数据库中,我有一个表" my_table"在列(a,b)上使用主键。

我编写了下面的查询,以便插入此表,以确保永远不会违反主键约束。

INSERT INTO my_table(a, b, c, d, e, f)
  (SELECT 'a1',
          'b1',
          'c1',
          1442849052013,
          1,
          FALSE
   FROM
     (SELECT 'a1'::VARCHAR(100) AS a,
             'b1'::VARCHAR(50) AS b) AS new_fields
   LEFT OUTER JOIN my_table AS old_fields ON (new_fields.a = old_fields.a
                                              AND new_fields.b = old_fields.b)
   WHERE old_fields.a IS NULL);  

由于多个此类查询因并发运行的线程而被触发,我有时会得到

  

PSQLException:重复键值违反唯一约束   " my_table_pkey&#34 ;.细节:键(a,b)=(a1,b1)已经存在。

我无法理解这个查询如何导致指定的错误情况,因为此查询会插入" my_table"只有在缺少主键列并且在同一查询中检查此条件时才会这样做。

如果这是一个有效的场景,这是不是意味着postgreSQL中的查询执行不是原子的?

有人可以解释一下......

此处,Select For Update语法也不会起作用,因为Select For Update会对所选行进行锁定,并且我想插入一行(如果该行尚不存在)。

1 个答案:

答案 0 :(得分:2)

PostgreSQL中的默认事务隔离级别,read committed,没有看到任何未提交的数据。

因此,如果插入了另一个未提交的交易(' a1',' b1'),则其他交易无法看到。

但是,约束的存在将保证在第一个事务已回滚之前,另一个事务的尝试插入(' a1',' b1')无法完成(并且您的事务可以成功完成)或已提交(并且您的事务将因违反约束而失败)。

完整的说明在documentation