我将基于PostgreSQL构建一个锁定系统,我有两个方法,
对于
这看起来很简单,但它并没有奏效。奇怪的是,我认为
只有当目标行的
为了再现这个问题,我写了一个简单的测试:
acquire
和release
。对于
acquire
方法,它的工作原理如下:BEGIN
while True:
SELECT id FROM my_locks WHERE locked = false AND id = '<NAME>' FOR UPDATE
if no rows return:
continue
UPDATE my_locks SET locked = true WHERE id = '<NAME>'
COMMIT
break
对于release
操作
BEGIN
UPDATE my_locks SET locked = false WHERE id = '<NAME>'
COMMIT
这看起来很简单,但它并没有奏效。奇怪的是,我认为
SELECT id FROM my_locks WHERE locked = false AND id = '<NAME>' FOR UPDATE
只有当目标行的
locked
为 false
时,才应该仅获取目标行上的锁。但实际情况并非如此。不知何故,即使不存在 locked = false
的行,它也会获取锁。结果,我遇到了死锁问题。情况看起来像这样:
在等待 SELECT FOR UPDATE
时,释放正在做无限循环,而同时它因无缘无故持有锁。为了再现这个问题,我写了一个简单的测试:
https://gist.github.com/victorlin/d9119dd9dfdd5ac3836b
你可以使用psycopg2
和 pytest
运行它,记得更改数据库设置并运行。pip install pytest psycopg2
py.test -sv test_lock.py
REPEATABLE READ
,稍后会检查一下。 - Fang-Pen LinREAD COMMITTED
。 - Kevin