提交后保持对数据库对象的锁定

col*_*ind 5 python django postgresql postgresql-9.3

我正在选择一些对象进行更新,然后对其进行操作

obj = Model.objects.select_for_update().get(id=someID)
obj.somefield = 1
obj.save()
Run Code Online (Sandbox Code Playgroud)

我仍然需要 FOR UPDATE锁定这个对象.PostgreSQL文档说FOR UPDATE锁定将一直存在,直到事务结束,这将结束,因为save将触发提交.即使我将手动管理提交,我需要将一些信息保存到数据库(为此我需要提交).

那么,在这种情况下我能做些什么呢?如果我将再次选择对象,则在设置新锁之前,其他一些进程可能会对此对象执行更改.

(我正在使用django 1.7和postgresql 9.3)

Cra*_*ger 2

事务提交或回滚后,您无法持有行锁。

这可能是咨询锁的合理用例,但由于所提供的细节有限,很难说清楚。咨询锁可以在会话级别运行,跨越事务边界。

你不能(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.
Run Code Online (Sandbox Code Playgroud)

所以我认为咨询锁几乎是你唯一的选择。


顺便说一下,处理这个问题的通常方法是让其他任务在两者之间进行更改。确保每个事务都使对象处于有意义的合理状态。如果其他人在你的两个更改之间进行了更改,请进行设计,这样就可以了。

为了避免覆盖之间所做的更改,您可以使用乐观并发控制,也称为乐观锁定,使用行版本列。如果您看到有人潜入并进行了更改,您可以重新加载对象以获取新版本,重复您的更改,然后再次尝试保存。不幸的是,与 Hibernate 等更复杂的 ORM 不同,Django 看起来并没有内置对乐观并发控制的支持,但似乎有扩展添加了它。