DatabaseError:当前事务被中止,命令被忽略直到事务块结束

jac*_*ack 238 python django postgresql psycopg2

我收到的消息有很多错误:

"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"
Run Code Online (Sandbox Code Playgroud)

之后从python-psycopg更改为python-psycopg2作为Django项目的数据库引擎.

代码保持不变,只是不知道这些错误来自哪里.

ʇsә*_*ɹoɈ 169

这是postgres在查询产生错误并且您尝试在没有先回滚事务的情况下运行另一个查询时所执行的操作.(您可能会将其视为安全功能,以防止您破坏数据.)

要解决这个问题,您需要弄清楚代码中执行错误查询的位置.在postgresql服务器中使用log_statementlog_min_error_statement选项可能会有所帮助.

  • 与服务器通信的方法可能并不重要,但是您可能会在某种程度上默认使用自动提交模式而新版本没有自动提供模式.错误可能仍然发生,但您可能更容易错过它.自旧版本以来,数据类型转换或其他内容也可能已更改.无论如何,最好的解决方法是追踪错误的查询,以便您可以看到它有什么问题. (4认同)
  • 在 psycopg 中:`conn.rollback()` (2认同)

Anu*_*pta 131

要消除错误,请在修复代码后回滚最后一个(错误的)事务:

from django.db import transaction
transaction.rollback()
Run Code Online (Sandbox Code Playgroud)

您可以使用try-except来防止错误发生:

from django.db import transaction, DatabaseError
try:
    a.save()
except DatabaseError:
    transaction.rollback()
Run Code Online (Sandbox Code Playgroud)

参考:Django文档

  • 这解决了核心问题,并允许您在导致中止事务的语句之后进行恢复. (3认同)
  • 为什么使用`IntegrityError`而不是基类`DatabaseError`? (3认同)

Mic*_*ant 50

所以,我遇到了同样的问题.我在这里遇到的问题是我的数据库没有正确同步.简单的问题似乎总是引起最大的焦虑......

要在您的应用程序目录中,在终端内同步您的django数据库,请键入:

$ python manage.py syncdb
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,如果您使用的是django-south,则运行'$ python manage.py migrate'命令也可以解决此问题.

快乐的编码!

  • 我通过`python manage.py migrate <app>`...为我的所有应用程序修复了类似的方法. (5认同)
  • 赞成陈述明显.我不会给这个不止一个upvote,因为它可能不是所寻求的答案. (3认同)
  • @Clayton - 你不说,但我假设你正在使用`django-south` - `migrate`命令没有内置到django中. (3认同)

pri*_*stc 33

根据我的经验,这些错误就是这样发生的:

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
Run Code Online (Sandbox Code Playgroud)

第二个查询没有任何问题,但是由于捕获了真正的错误,第二个查询是提出(信息量少)信息的错误.

编辑:这只有在except子句捕获IntegrityError(或任何其他低级数据库异常)时才会发生,如果你发现类似DoesNotExist这样的错误,则不会出现错误,因为DoesNotExist不会破坏事务.

这里的教训是不要尝试/ except/pass.


小智 28

在Flask中你只需要写:

curs = conn.cursor()
curs.execute("ROLLBACK")
conn.commit()
Run Code Online (Sandbox Code Playgroud)

PS文档到这里https://www.postgresql.org/docs/9.4/static/sql-rollback.html

  • 当 Jupyter Notebook 发生错误时,此解决方案也有很大帮助。 (2认同)

Seb*_*ian 16

我认为使用PostgreSQL时,priestc提到的模式更可能成为此问题的常见原因.

但是我觉得模式有用,我不认为这个问题应该是一直避免它的原因.例如:

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

do_something_with_profile(profile)
Run Code Online (Sandbox Code Playgroud)

如果您对此模式感觉不错,但想要避免在整个地方使用显式事务处理代码,那么您可能需要考虑启用自动提交模式(PostgreSQL 8.2+):https://docs.djangoproject.com/en/ 开发/ REF /数据库/#自动提交模式

DATABASES['default'] = {
    #.. you usual options...
    'OPTIONS': {
        'autocommit': True,
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定是否有重要的性能考虑(或任何其他类型).


Zvi*_*Zvi 12

你只需要运行

rollback;
Run Code Online (Sandbox Code Playgroud)

在 PostgreSQL 中就是这样!


小智 8

只需使用回滚

示例代码

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);")
Run Code Online (Sandbox Code Playgroud)


小智 8

我这里刚刚遇到类似的错误。我在此链接中找到了答案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()
Run Code Online (Sandbox Code Playgroud)

执行此操作,您发送到 postgresql 的以下查询将不会返回错误。


tut*_*uju 6

如果您在交互式shell中获得此功能并需要快速修复,请执行以下操作:

from django.db import connection
connection._rollback()
Run Code Online (Sandbox Code Playgroud)

最初在这个答案中看到


fai*_*gir 6

postgres终端上运行故障事务时遇到了类似的行为.在此之后没有任何事情发生,因为database它处于状态error.但是,如果您能够避免,那么就像快速解决一样rollback transaction.以下为我做了诀窍:

COMMIT;


Dan*_*kov 5

我有 silimar 问题。解决方案是迁移 db (manage.py syncdb或者manage.py schemamigration --auto <table name>如果您使用南)。


wat*_*nic 5

在 Flask shell 中,我所需要做的就是session.rollback()克服这个问题。