メッセージで多くのエラーが発生しました:
"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"
djangoプロジェクトのデータベースエンジンとしてpython-psycopgからpython-psycopg2に変更した後。
コードは同じままで、それらのエラーの原因がわからないだけです。
これは、クエリがエラーを生成し、最初にトランザクションをロールバックせずに別のクエリを実行しようとしたときにpostgresが行うことです。 (データを破損しないようにするための安全機能と考えるかもしれません。)
これを修正するには、コード内のどこで不良クエリが実行されているかを把握する必要があります。 postgresqlサーバーで log_statement および log_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 dbをアプリディレクトリ内、ターミナル内から同期するには、次のように入力します。
$ python manage.py syncdb
編集:Django-southを使用している場合は、「$ python manage.py migrate」コマンドを実行してもこの問題が解決する場合があります。
ハッピーコーディング!
私の経験では、これらのエラーは次のように発生します。
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を実行しないことです。
Flaskでは、次のように書くだけです。
curs = conn.cursor()
curs.execute("ROLLBACK")
conn.commit()
追伸ここにドキュメントがあります https://www.postgresql.org/docs/9.4/static/sql-rollback.html
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-mode
DATABASES['default'] = {
#.. you usual options...
'OPTIONS': {
'autocommit': True,
}
}
パフォーマンスに関する重要な考慮事項(またはその他のタイプ)があるかどうかはわかりません。
インタラクティブシェルでこれを取得し、簡単な修正が必要な場合は、次のようにします。
from Django.db import connection
connection._rollback()
元々 この回答
postgres
端末で誤動作したトランザクションを実行しているときに、同様の動作が発生しました。 database
はerror
の状態にあるため、この後は何も実行されませんでした。ただし、rollback transaction
を回避する余裕がある場合は、簡単な修正として。以下は私のためにトリックをしました:
COMMIT;
シリマーの問題があります。解決策は、db(南を使用する場合はmanage.py syncdb
またはmanage.py schemamigration --auto <table name>
)を移行することでした。
ロールバックを使用するだけです
サンプルコード
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);")
@priestcと@Sebastianへの応答として、このようなことをしたらどうでしょうか?
try:
conn.commit()
except:
pass
cursor.execute( sql )
try:
return cursor.fetchall()
except:
conn.commit()
return None
私はこのコードを試してみましたが、うまくいくようで、エラーを気にせずに静かに失敗し、クエリが良いときに動作します。
私もこのエラーが発生しましたが、コードが125文字の文字列を100文字の列に保存しようとした、より関連性の高い別のエラーメッセージをマスクしていました。
DatabaseError: value too long for type character varying(100)
上記のメッセージを表示するには、コードをデバッグする必要がありました。
DatabaseError: current transaction is aborted
Flask Shellでは、これをすり抜けるにはsession.rollback()
が必要でした。
@AnujGuptaの答えは正しいと思います。ただし、ロールバック自体が例外を発生させる可能性があるため、キャッチして処理する必要があります。
from Django.db import transaction, DatabaseError
try:
a.save()
except DatabaseError:
try:
transaction.rollback()
except transaction.TransactionManagementError:
# Log or handle otherwise
さまざまなsave()
の場所でこのコードを書き換えている場合は、extract-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()
を抽出メソッドとして保持すると便利です。
これは私にとって非常に奇妙な動作です。誰もセーブポイントを考えていないことに驚いています。私のコードでは、クエリに失敗すると予想される動作が発生しました:
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
この問題に遭遇しました。エラートランザクションが正しく終了していないため、エラーが発生しました。トランザクション制御コマンドのpostgresql_transactions
が見つかりました here
トランザクション制御
次のコマンドは、トランザクションを制御するために使用されます
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