2012-12-05 56 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對不起,我被困在這一個。 –