313

メッセージで多くのエラーが発生しました:

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

Django プロジェクトのデータベース エンジンとして python-psycopg から python-psycopg2 に変更された後。

コードは同じままですが、これらのエラーの原因がわかりません。

4

21 に答える 21

215

これは、クエリがエラーを生成し、最初にトランザクションをロールバックせずに別のクエリを実行しようとしたときにpostgresが行うことです。(データが破損しないようにするための安全機能と考えるかもしれません。)

これを修正するには、コードのどこで不正なクエリが実行されているかを把握する必要があります。postgresqlサーバーでlog_statementおよびlog_min_error_statementオプションを使用すると役立つ場合があります。

于 2010-06-05T06:16:39.440 に答える
149

エラーを取り除くには、コードを修正した後、最後の (エラーのある) トランザクションをロールバックします。

from django.db import transaction
transaction.rollback()

try-except を使用して、エラーの発生を防ぐことができます。

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

参照:Djangoのドキュメント

于 2012-10-22T08:16:06.160 に答える
52

だから、私はこの同じ問題に遭遇しました。ここで私が抱えていた問題は、データベースが適切に同期されていなかったことです。単純な問題は常に最も不安を引き起こすようです...

django db を同期するには、アプリ ディレクトリ内からターミナル内で次のように入力します。

$ python manage.py syncdb

編集: django-south を使用している場合は、'$ python manage.py migrate' コマンドを実行すると、この問題も解決される可能性があることに注意してください。

ハッピーコーディング!

于 2011-10-10T19:54:22.090 に答える
41

私の経験では、これらのエラーは次のように発生します。

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

2番目のクエリには何も問題はありませんが、実際のエラーが検出されたため、2番目のクエリは(情報量がはるかに少ない)エラーを発生させるクエリです。

編集:これは、except句がキャッチした場合IntegrityError(または他の低レベルのデータベース例外)にのみ発生します。このようなDoesNotExistエラーがキャッチされた場合DoesNotExist、トランザクションが破損しないため、エラーは発生しません。

ここでのレッスンは、try /except/passを実行しないことです。

于 2012-05-03T18:47:43.137 に答える
17

PostgreSQL を使用している場合、priestc が言及しているパターンがこの問題の通常の原因である可能性が高いと思います。

ただし、パターンには有効な用途があると感じており、この問題が常に回避する理由になるとは思いません。例えば:

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/ dev/ref/databases/#autocommit モード

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

パフォーマンスに関する重要な考慮事項 (またはその他のタイプ) があるかどうかはわかりません。

于 2012-07-06T16:23:33.603 に答える
7

対話型シェルでこれを取得し、迅速な修正が必要な場合は、次のようにします。

from django.db import connection
connection._rollback()

この回答で最初に見られた

于 2014-03-05T08:59:59.293 に答える
6

端末で誤動作したトランザクションを実行しているときに、同様の動作に遭遇しましたpostgresdatabaseは の状態であるため、この後は何も実行されませんでしerrorた。ただし、回避する余裕がある場合は、簡単な修正としてrollback transaction. 以下は私のためにトリックをしました:

COMMIT;

于 2016-03-11T21:53:39.063 に答える
5

シリマーの問題があります。解決策は、dbを移行することでした(manage.py syncdbまたはmanage.py schemamigration --auto <table name>南を使用する場合)。

于 2012-08-02T07:55:18.177 に答える
1

@priestc と @Sebastian への返信として、このようなことをするとどうなりますか?

try:
    conn.commit()
except:
    pass

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

私はちょうどこのコードを試してみましたが、動作しているようで、エラーの可能性を気にすることなく静かに失敗し、クエリが適切な場合に動作します。

于 2013-05-17T15:21:21.737 に答える
1

@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()も、特定の処理が必要な場合に手動で使用する必要があり、一般的なデコレーターの処理では不十分な場合に備えて、抽出されたメソッドとして保持しておくと便利です。

于 2014-03-27T09:31:18.013 に答える
1

私もこのエラーが発生しましたが、コードが125文字の文字列を100文字の列に格納しようとしていた別のより関連性の高いエラーメッセージを隠していました:

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

上記のメッセージが表示されるようにするには、コードをデバッグする必要がありました。

DatabaseError: current transaction is aborted
于 2013-02-13T21:57:45.540 に答える
-7

「set_isolation_level(0)」を介してトランザクションを無効にすることができます

于 2011-12-08T02:43:08.190 に答える