2016-10-22 48 views
0

我有一個Postgres(9.5)數據庫,用於由Web和後臺工作進程組成的應用程序。從不同的Postgres會話鎖定和解鎖

如果我們收到HTTP請求POST /items/123/steps,那麼web應用程序將排隊一個後臺任務,對123項目執行「工作流程步驟」並返回。該項目對應於Postgres的items表中的一行,並與id的值列123

的目標是爲加工某種方式鎖定項目123以便隨後對POST /items/123/steps請求將被拒絕,直到後臺任務解鎖項目123完成工作後。

同樣,對GET /items/123的請求必須返回一個屬性,指示項目123已被鎖定,以便UI可以將項目顯示爲當前正在處理的項目,直到後臺任務將其解鎖爲止。

因爲在後臺任務從隊列中取出之前可能會有延遲,所以後臺任務在開始執行時鎖定項目123是不夠的。我希望項目123被標記爲從最初的POST Web請求被鎖定,直到後臺任務完成爲止,以便該項目顯示爲在鎖定後臺任務被提取之前進入的任何Web請求。

如果可能,我想使用Postgres來完成此操作。不過,我已經找到了選擇似乎並不工作:在事務結束時,這發生在我的網頁處理程序返回

  • Row locks被釋放。後臺任務在不同的事務中執行其工作。所以我不能做SELECT FOR UPDATE項目123.
  • 會話級別advisory lock更接近,除非如果我從Web進程獲得它,我無法從工作進程解鎖它,因爲Web和工作進程每個建立自己的Postgres會話。

我可以解決此通過實現一個特設的鎖定機制:一個locked列添加到items並在網絡端點在後臺任務,將其設置爲TRUE然後回到FALSE。如果存在一個更標準的方法,但我寧願這樣做。

附加信息:這是一個Python項目,我使用SQLAlchemy從(Flask)Web應用程序和(Celery)後臺任務中訪問Postgres。如果有另一種經過驗證的方式來完成這些適用於我的工具的目標。

回答

1

您的「解決方法」使用locked列實際上是正確的解決方案。

正如您正確觀察的那樣,無論是常規鎖還是諮詢都不能很好地適應您的情況。