2012-06-26 72 views
1

當與多個進程/工作人員與Gunicorn運行Django我遇到了一些手動MySQL數據庫事務的死鎖問題。Django數據庫事務和死鎖

DatabaseError(1205, 'Lock wait timeout exceeded; try restarting transaction') 

我的設置使用多個數據庫,我的函數需要傳遞數據庫才能在調用它時使用。出於這個原因,我不能使用標準Django transaction decorators,因爲db需要被硬編碼爲參數。我檢查了裝飾代碼來看看事務是如何管理的,我的功能看起來像這樣:

from django.db import connections 

def process(self, db, data): 

    # Takeover transaction management 
    connections[db].enter_transaction_management(True) 
    connections[db].managed(True) 

    # Process 
    try: 
     # do things with my_objects... 
     for obj in my_objects: 
      obj.save(using=db) 
     connections[db].commit() 
    except Exception as e: 
     connections[db].rollback() 
    finally: 
     connections[db].leave_transaction_management() 

任何人能發現什麼可能是錯的怎麼回事?

回答

3

請注意,您可能想使用更清晰的with式樣的語法。以下內容應與上面的代碼相同,但更多是pytonic。

from django.db import transaction 
from __future__ import with_statement 

def process(self, db, data): 

    with transaction.commit_on_success(using=db): 
     # do things with my_objects... 
     for obj in my_objects: 
      obj.save(using=db) 

或具有裝飾

from django.db import transaction 

@transaction.commit_on_success(using=db) 
def process(self, db, data):  

    # do things with my_objects... 
    for obj in my_objects: 
     obj.save(using=db) 

這可能沒有什麼解決您的死鎖問題..

你可能有降低你的事務隔離級別的成功。這默認在mysql到REPEATABLE READ這對大多數用法來說太嚴格了。 (甲骨文默認爲READ COMMITTED「)

你可以做到這一點通過添加以下內容到settings.py

MYSQL_DATABASE_OPTIONS = {'init_command': 'SET storage_engine=INNODB; SET 
       SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;'} 

DATABASES = { 
    'default': { # repeat for each db 
     'ENGINE': ... etc 
     ... 
     ... 
     'OPTIONS': MYSQL_DATABASE_OPTIONS 
     } 
    }