2015-08-25 25 views
4

我選擇了更新一些對象,然後在其上保持數據庫對象的鎖後提交

obj = Model.objects.select_for_update().get(id=someID) 
obj.somefield = 1 
obj.save() 

我仍然需要執行的操作,以保持FOR UPDATE鎖定此對象。 PostgreSQL文檔說,FOR UPDATE鎖將活到事務結束,這將結束,因爲保存將觸發提交。 即使我手動管理提交,我需要保存一些信息到數據庫(爲此我需要提交)。

那麼,在這種情況下我能做些什麼呢? 如果我將再次選擇對象,則在設置新鎖之前,其他某個進程可能會對此對象執行更改。

(我使用Django 1.7和PostgreSQL 9.3)

回答

2

事務提交或回滾之後,你不能讓一個行鎖。

對於advisory locks,這可能是一個合理的用例,雖然很難說所提供的有限細節。諮詢鎖可以在會話級操作,跨越事務邊界。

你不能(AB)使用WITH HOLD光標:

test=> DECLARE test_curs CURSOR WITH HOLD FOR SELECT * FROM dummy FOR UPDATE; 
ERROR: DECLARE CURSOR WITH HOLD ... FOR UPDATE is not supported 
DETAIL: Holdable cursors must be READ ONLY. 

所以我想諮詢鎖幾乎是唯一的選擇。


處理這個,順便的常用方法,是其他任務進行更改之間。確保每筆交易都將物體置於明智的狀態。如果其他人在兩次更改之間進行更改,則可以設計一些事情。

爲避免覆蓋您在兩者之間所做的更改,您可以使用optimistic concurrency control,也稱爲樂觀鎖定,使用行版本列。如果您看到有人偷偷摸摸地做出更改,請重新加載對象以獲取新版本,然後重複更改並再次嘗試保存。不幸的是,與像Hibernate這樣更復雜的ORM不同,它看起來並不像Django內置對樂觀併發控制的支持,但似乎有擴展可以添加它。