Isn't PostgreSQL single query execution atomic?
本问题已经有最佳答案,请猛点这里访问。
在我的PostgreSQL数据库中,我有一个表"我的表",列上有主键(A,B)。
我在下面为这个表中的插入编写了查询,以确保不会违反主键约束。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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: duplicate key value violates unique constraint
"my_table_pkey". Detail: Key (a, b)=(a1, b1) already exists.
我无法理解此查询如何导致指定的错误条件,因为只有在缺少主键列并且正在同一查询中检查此条件的情况下,此查询才会插入"我的表"。
如果这是一个有效的场景,这是否意味着PostgreSQL中的查询执行不是原子的?
有人能解释一下…
在这里,select for update语法将不起作用,因为select for update会锁定选定的行,如果该行不存在,我希望插入该行。
PostgreSQL中的默认事务隔离级别read committed没有看到任何未提交的数据。
因此,如果另一个未提交的事务已插入("A1"、"B1"),则其他事务将看不到它。
但是,约束的存在将确保在第一个事务回滚(并且您的事务可以成功完成)或提交(并且您的事务将因违反约束而失败)之前,另一个事务尝试插入("a1"、"b1")的操作无法完成。
文件中有完整的解释。