2011-08-22 18 views
13

我使用MySQL與InnoDB引擎和REPEATABLE-READ隔離級別。這是一個安全的方式來增加和獲得在Django計數器的價值?

我已經寫了一個函數,我認爲應該原子地增加一個IntegerField,並給我增量後的值。我想知道我的代碼是否對併發問題有效。

我的代碼如下所示:

class MyModel(models.Model): 
    version = models.IntegerField() 

    @staticmethod 
    @transaction.commit_on_success 
    def acquire_version(pk): 
    MyModel.objects.filter(pk = pk).update(version = F('version') + 1) 
    return MyModel.objects.get(pk = pk).version 

我的想法是,在兩個併發調用,更新將相互互相排斥,因爲一個寫鎖,然後REPEATABLE-READ應該保證我的後續。在UPDATE之後get會給我值。我對嗎?

(這不是一般的「我該怎麼辦原子增量?」這個問題,有已其中的一個。這是這一個特殊的方式是否有效。)

+0

你有沒有看着http://stdbrouw.github.com/django-locking/ - 我假定你這樣做是對樂觀鎖定 – dstarh

+0

相關http://stackoverflow.com/questions/1598932/django中的反原子增量 –

回答

1

的一般規則,OF-拇指是any sort of custom queries or customized query behavior should go into manager methods. 這對你的情況是有道理的,因爲你可以增加,保存和返回在非常低的級別的版本號:在實際查詢期間。

因此,使用管理器(object = MyManager())和寫一個遞增的版本號的SQL查詢(UPDATE mytable SET version=(version+1) WHERE pk=pk,見here),並立即返回模型實例的增加的版本,可以執行任何其他呼叫之前。

又見Managers

+0

好的,但問題中給出的代碼是正確還是錯誤? – kdt

+0

我認爲它更危險,因爲.update()的實際實現可以獨立於Django版本。此外,你正在做一個雙重的,甚至可能是三雙查找。老實說,我不知道它是否(現在)是正確的。 – Remi

相關問題