使用 Django ORM 捕获竞争条件的正确方法 + MySQL/InnoDB
我的应用程序的一部分存在竞争条件,其中多个线程最终可能创建相同的持久对象。所以我实现了如下所示的代码:
from foobar.models import Bar
def testomatic(request):
bar = None
tries = 0
while not bar:
try:
bar = Bar.objects.get(b=2)
except Bar.DoesNotExist:
time.sleep(10) # put in here to force the race condition
bar = Bar(a = 2, b = 2)
try:
bar.save()
except IntegrityError:
tries += 1
bar = None
if tries > 1:
raise Exception("something bad happened")
return HttpResponse("tries = %s" % tries)
这在我的测试环境中工作正常 - 但是当我使用“真实”类运行它时,它似乎旋转,反复从 get() 中得不到任何东西,但总是得到一个 IntegrityError在保存()上。
我使用 MySQL/InnoDB 作为数据库引擎。 MVCC 处理是否存在某些问题,导致我无法获取记录,但在尝试创建记录时却出现重复键错误?
One part of my application has a race condition where multiple threads could end up creating the same persistent object. So I have implemented code that looks like this:
from foobar.models import Bar
def testomatic(request):
bar = None
tries = 0
while not bar:
try:
bar = Bar.objects.get(b=2)
except Bar.DoesNotExist:
time.sleep(10) # put in here to force the race condition
bar = Bar(a = 2, b = 2)
try:
bar.save()
except IntegrityError:
tries += 1
bar = None
if tries > 1:
raise Exception("something bad happened")
return HttpResponse("tries = %s" % tries)
And this works OK in my test environment -- but when I run this with "real" classes, it seems to spin, repeatedly getting nothing from the get(), but always getting an IntegrityError on the save().
I'm using MySQL/InnoDB as a database engine. Is there something about the MVCC handling that is preventing me from getting a record, but giving me a duplicate key error when I try to create it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正确的方法是使用原始 SQL,以便在执行初始 SELECT 时锁定表,然后创建并保存对象(如果对象不存在),然后解锁表。
The correct way to do this is to drop to raw SQL so that you can lock the table when doing the initial SELECT, and then creating and saving the object if it does not exist, then unlocking the table.