提问人:Arti 提问时间:11/10/2023 最后编辑:Arti 更新时间:11/13/2023 访问量:50
Django 增量字符串值,没有竞争条件
Django increment string value without race condition
问:
在保存时,我想收到像 .我实现了以下代码:name, name(1), name(2)
with transaction.atomic():
same_name_count = Folder.objects.filter(
owner=validated_data["owner"],
name__iregex=r"%s(\s\(\d+\))?" % validated_data["name"],
).count()
if same_name_count:
validated_data["name"] = f"{validated_data['name']} ({same_name_count+1})"
folder = Folder.objects.create(**validated_data)
但是当我在芹菜任务中运行此代码时,我仍然收到竞争条件并收到相同的名称。我还尝试以某种方式锁定所有行并获得正确的计数select_to_update
我的模型如下所示:
class Folder(models.Model):
owner = models.ForeignKey('User')
name = models.CharField(max_length=255)
答:
3赞
Bartosz Stasiak
11/10/2023
#1
select_for_update
将锁定表中所有选定的行,但不会阻止添加新行。
您需要做的是锁定其他表中的行。这样,事务将等到此锁定行被解锁。
在您的情况下,最合适的是桌子。User
示例代码如下:
with transaction.atomic():
# Assuming validated_data["owner"] is an id of the user.
# If its the User objects then add .id at the end
folder_owner = User.objects.select_for_update().get(id=validated_data["owner"])
same_name_count = Folder.objects.filter(
owner=folder_owner,
name__iregex=r"%s(\s\(\d+\))?" % validated_data["name"],
).count()
if same_name_count:
validated_data["name"] = f"{validated_data['name']} ({same_name_count+1})"
folder = Folder.objects.create(**validated_data)
评论
0赞
Bill Karwin
11/10/2023
MySQL 还具有获取建议锁的功能,请参阅 dev.mysql.com/doc/refman/8.0/en/locking-functions.html。这使用与表锁相同的机制,但不会锁定任何表或行。
0赞
Arti
11/10/2023
谢谢,没想到我需要锁定用户以防止插入。它正在工作
评论
name(1)
name(1)