我有其經由以下命令創建和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
因此,鎖在這種情況下起作用,但不能遞歸地工作。