我有其经由以下命令创建和PostgreSQL中填充的表:Django原子选择更新不锁定表的递归调用?
CREATE TABLE my_lock (
id integer,
CONSTRAINT id_pkey PRIMARY KEY (id)
) ;
INSERT INTO my_lock VALUES (1) ;
INSERT INTO my_lock VALUES (2) ;
该表由以下的Django模型
from django.db import models
from django.db import transaction
class MyLock(models.Model):
class Meta(object):
db_table = 'my_lock'
接着表示,我有以下几种方法:
from contextlib import contextmanager
@contextmanager
def acquire_lock():
with transaction.atomic():
lock = MyLock.objects.select_for_update().filter(id=1).first()
yield lock
def first_method():
print "In first method"
with acquire_lock():
print "Lock acquired in first_method()"
second_method()
def second_method():
print "In second method"
first_method()
acquire_lock()
方法是一个Python生成器,它运行一个SELECT FOR UPDATE
在事务中查询。这应该对id = 1的行进行锁定,并且由于调用yield lock
时事务未完成,请持续保持该锁定。
因此,如果我们调用first_method()
,以下输出应该打印:
In first method
Lock acquired in first_method()
In second method
In first method
然而,在现实中上调用first_method()
,下面会打印:
In first method
Lock acquired in first_method()
In second method
In first method
Lock acquired in first_method()
In second method
In first method
Lock acquired in first_method()
In second method
In first method
Lock acquired in first_method()
In second method
(这一直持续到RuntimeError: maximum recursion depth exceeded
)
我在这里错过了一些东西。这怎么会发生? PostgreSQL中的行锁如何被多次获取?
编辑:
如果我改变first_method()
到:
def first_method():
print "In first method"
with acquire_lock():
print "Lock acquired in first_method()"
i = 1
while True:
i = i + 1
i = i - 1
和,现在就从两个不同终端(或壳),first_method()
其中一个打印如下:
In first method
Lock acquired in first_method()
第二个打印以下内容:
In first method
因此,锁在这种情况下起作用,但不能递归地工作。