[Python] DatabaseError:當前事務被中止,直到事務塊結束時忽略命令


Answers

為了消除錯誤,在修復代碼後回滾最後一個(錯誤的)事務

from django.db import transaction
transaction.rollback()

您可以使用try-except來防止發生錯誤:

from django.db import transaction, DatabaseError
try:
    a.save()
except DatabaseError:
    transaction.rollback()

請參閱: Django文檔

Question

我收到了很多錯誤消息:

"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"

在從python-psycopg更改為python-psycopg2作為Django項目的數據庫引擎後。

代碼保持不變,只是不知道這些錯誤來自哪裡。




我相信@ AnujGupta的回答是正確的。 然而,回滾本身可能會引發一個您應該捕獲並處理的異常:

from django.db import transaction, DatabaseError
try:
    a.save()
except DatabaseError:
    try:
        transaction.rollback()
    except transaction.TransactionManagementError:
        # Log or handle otherwise

如果您發現您在各種save()位置重寫此代碼,則可以提取-method方法:

import traceback
def try_rolling_back():
    try:
        transaction.rollback()
        log.warning('rolled back')  # example handling
    except transaction.TransactionManagementError:
        log.exception(traceback.format_exc())  # example handling

最後,你可以使用裝飾器來保護使用save()方法來對其進行美化:

from functools import wraps
def try_rolling_back_on_exception(fn):
    @wraps(fn)
    def wrapped(*args, **kwargs):
        try:
            return fn(*args, **kwargs)
        except:
            traceback.print_exc()
            try_rolling_back()
    return wrapped

@try_rolling_back_on_exception
def some_saving_method():
    # ...
    model.save()
    # ...

即使你實現了上面的裝飾器,仍然可以方便地將try_rolling_back()作為提取的方法保存,以防需要特定處理的情況下手動使用它,並且通用裝飾器處理不夠。




我也有這個錯誤,但它掩蓋了另一個更相關的錯誤消息,代碼試圖在100個字符列中存儲一個125個字符的字符串:

DatabaseError: value too long for type character varying(100)

我不得不通過代碼調試以顯示上述消息,否則顯示

DatabaseError: current transaction is aborted



只是使用回滾

示例代碼

try:
    cur.execute("CREATE TABLE IF NOT EXISTS test2 (id serial, qa text);")
except:
    cur.execute("rollback")
    cur.execute("CREATE TABLE IF NOT EXISTS test2 (id serial, qa text);")



根據我的經驗,這些錯誤以這種方式發生:

try:
    code_that_executes_bad_query()
    # transaction on DB is now bad
except:
    pass

# transaction on db is still bad
code_that_executes_working_query() # raises transaction error

第二個查詢沒有任何問題,但是由於真正的錯誤被捕獲,第二個查詢是引發(信息量更少)錯誤的查詢。

編輯:只有在except語句捕獲IntegrityError (或任何其他低級別的數據庫異常)時才會發生這種情況,如果發現類似DoesNotExist錯誤,則不會出現此錯誤,因為DoesNotExist不會破壞事務。

這裡的教訓是不要嘗試/除了/通過。




我有silimar問題。 解決方案是遷移數據庫(如果使用南,則可以使用manage.py syncdbmanage.py schemamigration --auto <table name> )。




如果你在交互式shell中得到這個,並且需要快速修復,請執行以下操作:

from django.db import connection
connection._rollback()

最初見於這個答案