2015-09-21 49 views
1

在我的postgresql數據庫中,我在列(a,b)上有一個包含主鍵的表「my_table」。是不是PostgreSQL單個查詢執行原子?

我寫了下面的嵌入式查詢到這個表,保證了主鍵約束從不侵犯。

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」。細節:鍵(a,b)=(a1,b1)已經存在。

我無法明白,這怎麼能查詢引到指定的錯誤條件作爲此查詢插入到「MY_TABLE」僅當它的主鍵列失蹤,這一狀況正在同一個查詢中檢查。

如果這是一個有效的情況下,並不意味着這在PostgreSQL中查詢執行不是原子?

有人能請解釋一下......

這裏,因爲選擇用於更新發生在選定行的鎖,我想插入一行,如果它不是已經存在選擇對於更新語法不會正常工作。

+0

這是我的理解,在大多數RDBMS查詢執行不是原子;這就是交易存在的原因。 – Uueerdo

+0

@ Uueerdo多個查詢的執行不是原子的,而是一個查詢的執行必須是原子的,不是? –

+0

請格式化您的SQL,使其更易於閱讀。 –

回答

2

PostgreSQL中的默認事務隔離級別,讀取提交,沒有看到任何未提交的數據。

因此,如果另一個未提交的事務已經插入(「A1」,「B1」),其他的事務不能看到它。

但是約束的存在將保證其他事務的企圖的插入(「A1」,「B1」)無法完成,直到第一個事務或者回滾(和你的交易能夠順利完成),或承諾(和你事務將違反約束而失敗)。

一個完整的解釋是在documentation

+0

非常感謝David解釋發生在我的查詢中的競爭條件。 您可以請求在Postgres中建議一種方法,只在該表的主鍵不存在於表中時才插入行嗎? 目前,我通過處理在發生唯一約束違例的情況下拋出的異常來解決這個問題。 –

+0

@VijayKansal:看到這裏:http:// stackoverflow。com/q/26577258/330315和這裏:http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-in-postgresql –

相關問題