2012-12-05 54 views
2

我在共享托管计划上运行一个小型Web应用程序。 我有一个“工人功能”,其中包含一个无限循环;循环会检查数据库中的任务队列以了解要执行的新操作。这需要使用@transaction.commit_manually来打败Django的缓存并获取每次迭代的最新信息。Django + MySQL:保存点不存在?

我最近实施DB的日志记录,因此需要使用保存点到我的工作器功能介绍 - 这样一来,如果有什么出错,我可以回滚到一个很好的保存点,登录到数据库,并进行直到我到达最终现在transaction.commit()

,不像我开发服务器,生产服务器给我的错误:

DatabaseError: (1305, 'SAVEPOINT s140364713719520_x1 does not exist') 

指向transaction.savepoint_rollback()呼叫在except块(见下文源)。开发服务器没有这样的问题;如果我在交互式shell中键入transaction.savepoint(),生产服务器会很高兴地生成保存点ID。

This is the outline of my code,如果它有任何帮助;我试图保持简洁。

如果有仁慈的Python专家出现在那里,请帮助我。我对此感到非常沮丧,尽管我觉得我在冷静地处理这件事方面做得很好。

回答

9

我有同样的偶尔复发讨厌的错误

OperationalError: (1305, 'SAVEPOINT {{name}} does not exist') 

和谷歌搜索没有说得清楚,但它是一种“正常”的并发问题。所以这是非确定性的,很难在开发环境中重现。

幸运的是它是本地化的,所以我让生产应用日志足够详细。

在MySQL中是有可能暗示结束交易的一些操作:

  • DDL语句(如CREATE TABLEALTER TABLE等)导致隐式提交。众所周知,MySQL中的DDL不是事务性的,
  • OperationalError: (1213, 'Deadlock found when trying to get lock; try restarting transaction')OperationalError: (1205, 'Lock wait timeout exceeded; try restarting transaction')导致隐式回滚。

所以第二种情况的结果确实有点“正常”。它可以通过下面的代码来表示:

# db is an exemplary database connection object, which 
# - supports nested (stacked) transactions, 
# - has autocommit on. 

db.begin() # START TRANSACTION 
try: 
    # no-conflict op 
    db.update() 

    db.begin() # SAVEPOINT sp1 
    try: 
    # conflict op, 
    # e.g. attempt to change exclusively locked rows by another transaction 
    db.update() 

    db.commit() # RELEASE SAVEPOINT sp1 
    except: 
    # Everything interesting happens here: 
    # - the change attempt failed with OperationalError: (1213, 'Deadlock...'), 
    # - the transaction is rolled back with all the savepoints, 
    # - next line will attempt to rollback to savepoint which no longer exists, 
    # - so will raise OperationalError: (1305, 'SAVEPOINT sp1 does not exist'), 
    # - which will shadow the original exception. 

    db.rollback() # ROLLBACK TO SAVEPOINT sp1 
    raise 

    db.commit() # COMMIT 
except: 
    db.rollback() # ROLLBACK 
    raise 
0

如果您查阅Django上与Savepoints相关的文档,提及并非所有MySQL Storage Engines都支持它们。基本上MyISAM不处理事务,所以你不能回滚和InnoDB。所以我会检查你的dev和prod表都使用相同的存储引擎类型。您可以通过运行检查:

SHOW CREATE TABLE mytable 
+0

我所有的表使用的是InnoDB,这两个网站上。 – egasimus

+0

@egasimus对不起,我被困在这一个。 –