[英]Django transaction.atomic() guarantees atomic READ + WRITE?
我需要確保從數據庫讀取並寫回的對象不能在此期間被另一個請求/進程修改。
transaction.atomic()保證嗎?
到目前為止我的測試告訴我沒有。 如果他們沒有任何問題,那么實現原子READS和WRITES的正確方法是什么?
我測試過的例子。
將Test類放在模型中的某個位置。 atomic_test.py和atomic_test2.py應保存為管理命令。 首先運行python manage.py atomic_test ,然后運行python manage.py atomic_test2 。 第二個腳本不會阻止,其更改將丟失。
models.py
class Test(models.Model):
value = models.IntegerField()
atomic_test.py
from django.core.management.base import NoArgsCommand
from django.db import transaction
from time import sleep
from core.models import Test
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list
def handle(self, **options):
Test.objects.all().delete()
t = Test(value=50)
t.save()
print '1 started'
with transaction.atomic():
t = Test.objects.all()[0]
sleep(10)
t.value = t.value + 10
t.save()
print '1 finished: %s' %Test.objects.all()[0].value
atomic_test2.py
from django.core.management.base import NoArgsCommand
from django.db import transaction
from time import sleep
from core.models import Test
class Command(NoArgsCommand):
option_list = NoArgsCommand.option_list
def handle(self, **options):
print '2 started'
with transaction.atomic():
t = Test.objects.all()[0]
t.value = t.value - 20
t.save()
print '2 finished: %s' %Test.objects.all()[0].value
Django的transaction.atomic()
是對數據庫事務工具的精簡抽象。 所以它的行為實際上取決於數據庫層,並且特定於數據庫的類型及其設置。 因此,要真正了解其工作原理,您需要閱讀並理解數據庫的事務文檔。 (例如,在PostgreSQL中,相關文檔是事務隔離和顯式鎖定 )。
至於您的特定測試用例,可以通過在Django查詢集上使用select_for_update()
方法來實現您想要的行為(如果您的數據庫支持它)。 就像是:
在atomic_test.py中
with transaction.atomic():
t = Test.objects.filter(id=1).select_for_update()[0]
sleep(10)
t.value = t.value + 10
t.save()
在atomic_test2.py中
with transaction.atomic():
t = Test.objects.filter(id=1).select_for_update()[0]
t.value = t.value - 20
t.save()
第二個應該阻塞,直到第一個完成,並看到新值60。
其他選項包括使用SERIALIZABLE
事務隔離級別或使用行鎖,但Django不提供方便的API來執行這些操作。
使用F函數在數據庫上進行原子更新會好得多:
from django.db.models import F
Test.objects.filter(id=1).update(value=F("value") + 10)
(這會生成類似"UPDATE test_test SET value = value + 10 WHERE id = 1"
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.