2012-08-01 62 views
1

我有點想知道我正在做一個大桌子的更新,我是否需要擔心鎖。在PostgreSQL中,對同一個表中的不同行進行多個更新,並存在鎖定衝突?

我有一個表看起來像這樣:

CREATE TABLE "ItemsToProcess"( 
"id" text, 
"WorkerInstanceId" text, 
"ProcessingStartTime" timestamp with time zone, 
"UpdatedTime" timestamp with time zone, 
CONSTRAINT "ITP_PK" PRIMARY KEY ("id") 
)WITH (
    OIDS=FALSE 
); 

最初,這個表有〜在這2.0萬行,並填寫,WorkerInstanceId只有ID和兩個時間戳爲空默認情況下,開頭的運行。

會發生什麼是一些工人應用程序(至少兩個,但將在生產中大約10-13)將從這個表中標記一批ID-s(我打算將batchSize設置爲200)以處理。處理過程中發生的事情現在無關緊要。 一批標記看起來是這樣的:

UPDATE "ItemsToProcess" 
    SET "WorkerInstanceId" = ?, "ProcessingStartTime" = current_timestamp() 
WHERE "WorkerInstanceId" is NULL 
LIMIT 200; 

我的問題是,我需要擔心鎖定我要去使得更新之前更新行?

Postgres的文件說:

ROW EXCLUSIVE

衝突與共享,共享ROW EXCLUSIVE,EXCLUSIVE,和ACCESS EXCLUSIVE鎖模式。

UPDATE,DELETE和INSERT命令獲取目標表上的此鎖定模式(除了任何其他引用的表上的ACCESS SHARE鎖定)。一般來說,這種鎖定模式將由修改表中數據的任何命令獲取。

所以我認爲,只要其中一個工作人員進行此更新,整個表就會被鎖定,200行將被更新,最後鎖定將被釋放。在鎖定到位之前,其他工作人員正在等待鎖定釋放。我是對的還是我想念什麼?

感謝您的幫助!

回答

1

你錯過了幾件事。

首先,PostgreSQL不提供更新的「LIMIT」選項。請參閱docs for UPDATE

其次,請注意「ROW EXCLUSIVE」與自身不衝突,它與「SHARE ROW EXCLUSIVE」不一致。因此,您的UPDATE語句可以安全地從多個工作人員併發運行。你仍然希望你的更新時間很低。但是,如果遇到問題,您已經有了一個內置的方法來調整該方法,即降低「batchSize」。

+0

謝謝!我想知道我可以做什麼來限制更新... – 2012-08-01 15:02:42

+1

對於較小的更新計數,使用'WH IN'子句和'id IN(SELECT t.id FROM thetable t LIMIT 200 ORDER BY id)'子句。請記住,如果沒有'ORDER BY',則使用'LIMIT'是非確定性的。 – 2012-08-01 23:29:31

4

UPDATE鎖定行,所以你不需要先鎖定它。如果您嘗試同時重疊UPDATE行,則第二個UPDATE將等待第一個事務提交或回滾。

您的方法的一個大問題 - 除了UPDATE沒有LIMIT子句這一事實外,多個工作人員都會嘗試抓取相同的行。這裏是發生了什麼:

worker1:過濾表,找到200行,並鎖定他們 worker1:開始更新行 worker2:過濾表,找到200行 worker2:嘗試啓動更新行,但已經選擇了相同行作爲worker1 因此它阻止worker1的鎖 worker1:完成更新行 worker2:鎖釋放後,重新檢查WHERE條件並找出沒有行 匹配了,因爲worker1已更新它們。更新零行。 ...並重復!

您需要:

  • 有一箇中央queue省高院在合適的併發安全的方式行;或
  • 分配工人不重疊的ID的範圍上

工作,至於LIMIT - 你可以使用WHERE id IN (SELECT t.id FROM thetable t LIMIT 200 ORDER BY id) - 但你有兩個選擇工人相同的行集更新的同樣的問題。

+1

考慮到這裏面臨的挑戰,現在也是考慮第三方工作隊列系統是否更好的選擇的好時機。一個爲PostgreSQL製作的小工具是[Job :: Machine](https://metacpan.org/module/Job::Machine)。還有其他一些選擇。 – 2012-08-02 00:57:26

+2

@MarkStosberg是的。我不想詳細討論排隊問題。還有skytools的PgQ:http://wiki.postgresql.org/wiki/PGQ_Tutorial – 2012-08-02 02:04:55

+0

感謝您的意見! – 2012-08-02 07:27:05

相關問題