簡體   English   中英

DatabaseError:當前事務被中止,在事務塊結束之前忽略命令?

[英]DatabaseError: current transaction is aborted, commands ignored until end of transaction block?

我收到了很多錯誤消息:

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

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

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

當查詢產生錯誤並且您嘗試運行另一個查詢而不首先回滾事務時,這就是 postgres 所做的。 (您可能會將其視為一項安全功能,以防止您破壞數據。)

要解決此問題,您需要找出代碼中執行錯誤查詢的位置。 在 postgresql 服務器中使用log_statementlog_min_error_statement選項可能會有所幫助。

要消除錯誤,請在修復代碼后回滾最后一個(錯誤的)事務

from django.db import transaction
transaction.rollback()

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

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

參考: Django 文檔

所以,我遇到了同樣的問題。 我在這里遇到的問題是我的數據庫沒有正確同步。 簡單的問題似乎總是引起最大的焦慮……

要同步您的 django 數據庫,請從您的應用程序目錄中的終端中鍵入:

$ python manage.py syncdb

編輯:請注意,如果您使用的是 django-south,運行“$ python manage.py migrate”命令也可以解決此問題。

快樂編碼!

在 Flask 中你只需要寫:

curs = conn.cursor()
curs.execute("ROLLBACK")
conn.commit()

PS 文檔在這里https://www.postgresql.org/docs/9.4/static/sql-rollback.html

根據我的經驗,這些錯誤是這樣發生的:

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不會破壞事務。

這里的教訓是不要嘗試/除外/通過。

我認為牧師提到的模式更有可能是使用 PostgreSQL 時出現此問題的常見原因。

但是我覺得這個模式有一些有效的用途,我不認為這個問題應該成為總是避免它的理由。 例如:

try:
    profile = user.get_profile()
except ObjectDoesNotExist:
    profile = make_default_profile_for_user(user)

do_something_with_profile(profile)

如果您確實對這種模式感到滿意,但想要避免到處都是顯式事務處理代碼,那么您可能需要考慮開啟自動提交模式(PostgreSQL 8.2+): https ://docs.djangoproject.com/en/ 開發/參考/數據庫/#autocommit-mode

DATABASES['default'] = {
    #.. you usual options...
    'OPTIONS': {
        'autocommit': True,
    }
}

我不確定是否有重要的性能考慮(或任何其他類型)。

只需使用回滾

示例代碼

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);")

如果您在交互式 shell 中遇到此問題並需要快速修復,請執行以下操作:

from django.db import connection
connection._rollback()

最初在這個答案中看到

我在postgres終端上運行故障事務時遇到了類似的行為。 此后什么也沒有發生,因為database處於error狀態。 但是,作為一個快速解決方案,如果您有能力避免rollback transaction 以下對我有用:

COMMIT;

我在這里遇到了類似的錯誤。 我在這個鏈接https://www.postgresqltutorial.com/postgresql-python/transaction/中找到了答案

client = PsqlConnection(config)
connection = client.connection
cursor = client.cursor

try:
   for query in list_of_querys:
      #query format => "INSERT INTO <database.table> VALUES (<values>)"
      cursor.execute(query)
      connection.commit()
except BaseException as e:
   connection.rollback()

執行此操作后,您發送到 postgresql 的以下查詢不會返回錯誤。

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

在 Flask shell 中,我需要做的就是使用session.rollback()來解決這個問題。

你只需要運行

rollback;

在 PostgreSQL 中,就是這樣!

我遇到了這個問題,由於錯誤事務沒有正確結束而出現錯誤,我在這里找到了事務控制命令的postgresql_transactions

交易控制

以下命令用於控制事務

BEGIN TRANSACTION − To start a transaction.

COMMIT − To save the changes, alternatively you can use END TRANSACTION command.

ROLLBACK − To rollback the changes.

所以我使用END TRANSACTION來結束錯誤TRANSACTION,代碼如下:

    for key_of_attribute, command in sql_command.items():
        cursor = connection.cursor()
        g_logger.info("execute command :%s" % (command))
        try:
            cursor.execute(command)
            rows = cursor.fetchall()
            g_logger.info("the command:%s result is :%s" % (command, rows))
            result_list[key_of_attribute] = rows
            g_logger.info("result_list is :%s" % (result_list))
        except Exception as e:
            cursor.execute('END TRANSACTION;')
            g_logger.info("error command :%s and error is :%s" % (command, e))
    return result_list

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

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

我必須通過代碼調試才能顯示上述消息,否則會顯示

DatabaseError: current transaction is aborted

回應@priestc 和@Sebastian,如果你做這樣的事情怎么辦?

try:
    conn.commit()
except:
    pass

cursor.execute( sql )
try: 
    return cursor.fetchall()
except: 
    conn.commit()
    return None

我剛剛嘗試了這段代碼,它似乎可以工作,默默地失敗而不必關心任何可能的錯誤,並且在查詢良好時工作。

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

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

如果您發現要在不同的save()位置重寫此代碼,則可以提取方法:

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()保留為提取方法仍然很方便,以防您需要在需要特定處理的情況下手動使用它,而通用裝飾器處理還不夠。

這對我來說是非常奇怪的行為。 我很驚訝沒有人想到保存點。 在我的代碼中,查詢失敗是預期的行為:

from django.db import transaction
@transaction.commit_on_success
def update():
    skipped = 0
    for old_model in OldModel.objects.all():
        try:
            Model.objects.create(
                group_id=old_model.group_uuid,
                file_id=old_model.file_uuid,
            )
        except IntegrityError:
            skipped += 1
    return skipped

我以這種方式更改了代碼以使用保存點:

from django.db import transaction
@transaction.commit_on_success
def update():
    skipped = 0
    sid = transaction.savepoint()
    for old_model in OldModel.objects.all():
        try:
            Model.objects.create(
                group_id=old_model.group_uuid,
                file_id=old_model.file_uuid,
            )
        except IntegrityError:
            skipped += 1
            transaction.savepoint_rollback(sid)
        else:
            transaction.savepoint_commit(sid)
    return skipped

我正在使用 python 包 psycopg2 並且在查詢時出現此錯誤。 我一直只運行查詢,然后運行執行函數,但是當我重新運行連接(如下所示)時,它解決了問題。 因此,重新運行腳本之上的內容,即連接,因為正如上面有人所說,我認為它丟失了連接或不同步或其他原因。

connection = psycopg2.connect(user = "##",
        password = "##",
        host = "##",
        port = "##",
        database = "##")
cursor = connection.cursor()

這是一個錯誤的 sql 執行問題,它不允許其他查詢執行,直到前一個查詢被掛起/回滾。

在 PgAdmin4-4.24 中有一個回滾選項,可以試試這個。

在此處輸入圖片說明

您可以通過“set_isolation_level(0)”禁用事務

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM