我有一個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。如果有另一種經過驗證的方式來完成這些適用於我的工具的目標。