簡體   English   中英

如何在PostgreSQL中處理競爭條件?

[英]How can I deal with a race condition in PostgreSQL?

我在Postgresql上遇到了一些錯誤,這些錯誤似乎與這種競爭狀況有關。

我有一個用Twisted Python編寫的進程/守護程序。 描述它的最簡單方法是作為Web爬網程序-它拉出一個頁面,解析鏈接並記錄所見內容。 由於HTTP阻止,Twisted運行了多個推遲到線程的“並行”進程。

這是比賽條件...

當我遇到網址縮短程序時,會發生以下邏輯:

result= """SELECT * FROM shortened_link WHERE ( url_shortened = %(url)s ) LIMIT 1;"""
if result:
   pass
else:
   result= """INSERT INTO shortened_link ( url_shortened ..."

引發了一個令人驚訝的數字或psycopg2.IntegrityError,因為違反了url_shortened上的唯一索引。

選擇/插入實際上確實並排運行。 據我所知,似乎有2個縮短的鏈接排在一起。

Process A: Select, returns Null
Process B: Select, returns Null
Process A: Insert , success
Process B: Insert , integrity error

任何人都可以提出任何提示/技巧來解決這個問題嗎? 我想避免顯式鎖定,因為我知道這會帶來其他一系列問題。

只需一個命令即可完成所有操作:

result= """
INSERT INTO shortened_link ( url_shortened ...
SELECT %(url)s
where not exists (
    select 1
    from shortened_link
    WHERE url_shortened = %(url)s
);"""

僅當該鏈接不存在時才插入。

確實沒有一種解決方案能夠避免需要處理唯一約束沖突錯誤的可能性。 如果您的框架無法做到這一點,那么我會將SQL包裝在可以的PL / pgSQL函數或過程

鑒於您可以處理錯誤,您也可能不測試唯一值的存在,而只嘗試插入,讓EXCEPTION子句處理任何錯誤。

您要么需要某種互斥鎖,要么必須忍受由於競爭條件而發生的冗余。

如果選擇使用互斥鎖-您不一定需要使用數據庫級鎖。 您可以簡單地鎖定Twisted進程以阻止其他線程處理類似的縮短的url。

如果選擇避免鎖定,請刪除url_shortened字段上的唯一約束。 您可以定期將這些記錄移到“干凈”表中,該表包含每個縮短的URL的唯一副本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM