2012-06-26 157 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 
     } 
    }