2016-11-18 111 views
1

我在Django中的transaction.atomic塊內運行以下代碼。Django保存點回滾捕獲完整性錯誤導致TransactionManagementError

@transaction.atomic() 
def test(): 
    a.save() 
    sid = transaction.savepoint() 
    try: 
     b.save() 
     transaction.savepoint_commit(sid) 
    except IntegrityError as e: 
     transaction.savepoint_rollback(sid) 
    c.save() 

此代碼給我下面的錯誤 -

TransactionManagementError 
An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. 

我跟着從官方文檔下面的鏈接。 https://docs.djangoproject.com/en/1.10/topics/db/transactions/#s-savepoint-rollback

我在這裏錯過了什麼?

編輯: - 添加堆棧跟蹤。

File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/models/manager.py", line 122, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/models/query.py", line 401, in create 
    obj.save(force_insert=True, using=self.db) 
    File "/Users/vibhor/Documents/juggernaut/user-persistence-service/books/models/books.py", line 243, in save 
    transaction.savepoint_rollback(sid) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/transaction.py", line 66, in savepoint_rollback 
    get_connection(using).savepoint_rollback(sid) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/base/base.py", line 328, in savepoint_rollback 
    self._savepoint_rollback(sid) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/base/base.py", line 288, in _savepoint_rollback 
    cursor.execute(self.ops.savepoint_rollback_sql(sid)) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/utils.py", line 79, in execute 
    return super(CursorDebugWrapper, self).execute(sql, params) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/utils.py", line 59, in execute 
    self.db.validate_no_broken_transaction() 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/base/base.py", line 429, in validate_no_broken_transaction 
    "An error occurred in the current transaction. You can't " 
TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. 
+0

請添加完整的錯誤回溯到您的文章!這樣我們可以看到哪個命令導致了問題。 –

回答

1

我認爲你正在運行到文檔中描述此問題:

保存點可以用來通過執行部分回滾從數據庫錯誤中恢復。如果您在atomic()區塊內執行此操作,則整個區塊仍會回滾,因爲它不知道您已經處理了較低級別的情況!爲了防止這種情況,你可以控制回滾行爲具有以下功能...

如前所述那裏,你可能想要做一個transaction.set_rollback(False),以防止整個原子塊被回滾。

現在,有沒有一個原因,你正在做這個手動?你的代碼貼可以完成同樣的事情用一個嵌套的原子塊,並作爲文檔註釋:

atomic()裝飾嵌套,它會創建一個保存點,以允許部分提交或回滾。強烈建議您使用atomic()而不是下面描述的功能。

1

正如documentation解釋說:

爲了保證原子,原子禁用一些API。嘗試提交,回滾或更改原子塊中數據庫連接的自動提交狀態將引發異常。

實現你想要什麼的正確方法是創建另一個atomic塊:

@transaction.atomic() 
def test(): 
    a.save() 
    try: 
     with transaction.atomic(): 
      b.save() 
    except IntegrityError: 
     #handle exception here... 
     ... 
    c.save() 
-1
@transaction.atomic() 
def test(): 
    a.save() 
    sid = transaction.savepoint() 
    try: 
     with transaction.atomic(): 
      b.save() 
      transaction.savepoint_commit(sid) 
    except IntegrityError as e: 
     transaction.savepoint_rollback(sid) 
    c.save() 

請檢查該