【问题标题】:DatabaseError: current transaction is aborted, commands ignored until end of transaction block?DatabaseError:当前事务被中止,在事务块结束之前忽略命令?
【发布时间】:2023-03-27 11:10:01
【问题描述】:

我收到了很多错误消息:

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

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

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

【问题讨论】:

  • 我很好奇您对这个问题的最终解决方案是什么?我也遇到了同样的问题,但是由于我的托管服务提供商没有记录查询错误,所以到目前为止还无法弄清楚出了什么问题。
  • 当我使用数据库表作为缓存后端时,我终于将我的问题归结为一个错误。 Django 错误:code.djangoproject.com/ticket/11569 StackOverflow 讨论:stackoverflow.com/questions/1189541/…
  • 仅供参考如果您只是在没有 django 的情况下使用 psycopg2,conn.rollback()(其中 conn 是您的连接对象)将清除错误,以便您可以运行其他查询

标签: python django postgresql psycopg2


【解决方案1】:

当查询产生错误并且您尝试运行另一个查询而不首先回滚事务时,这就是 postgres 所做的。 (您可能会将其视为一项安全功能,以防止您损坏数据。)

要解决此问题,您需要找出在代码中执行错误查询的位置。在您的 postgresql 服务器中使用 log_statementlog_min_error_statement 选项可能会有所帮助。

【讨论】:

  • 问题是当我使用 python-psycopg 时,没有出现此类错误。 psycopg2 是否实现了与 postgres 对话的不同机制?
  • 与服务器通信的方法可能无关紧要,但有可能您之前使用的版本默认为自动提交模式,而新版本则没有。该错误可能仍然发生,但您可能更容易错过它。自旧版本以来,数据类型转换或其他内容也可能发生了变化。无论如何,最好的解决办法是追踪错误的查询,这样您就可以看到它有什么问题。
【解决方案2】:

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

from django.db import transaction
transaction.rollback()

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

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

参考:Django documentation

【讨论】:

  • 这解决了核心问题,让您可以在导致事务中止的语句后恢复。
  • this,结合try / except。
  • 为什么使用IntegrityError而不是基类DatabaseError
  • 出于某种原因,我不得不将回滚移到“除外”部分之外。我使用的是 .bulk_create() 而不是 .save()
  • 在关注这个stackoverflow.com/a/15753000/573034之后使用django 1.4.16
【解决方案3】:

在 Flask 中你只需要写:

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

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

【讨论】:

  • 这个解决方案在Jupyter notebook出现错误时也有很大帮助。
  • 不错。它在 Jupyter 中帮助了我
  • 值得补充的是,这可以在 Flask 之外工作,并且似乎可以在您使用 psycopg2 的任何地方进行
【解决方案4】:

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

要同步您的 django 数据库,请从您的应用目录中的终端中输入:

$ python manage.py syncdb

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

编码愉快!

【讨论】:

  • 赞成陈述显而易见的事情。不过,我不会对此给予超过一票,因为这可能不是所寻求的答案。
  • 我通过python manage.py migrate <app>... 以类似的方式修复了我所有的应用程序。
  • @Clayton - 你没有说,但我假设你正在使用 django-south - migrate 命令没有内置到 django 中。
  • @GregBall- 这是正确的......我正在使用 django-south。抱歉没有具体说明。
  • 我在执行 syncdb 时遇到此错误 - 我认为这与 django 遍历表的顺序有关。
【解决方案5】:

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

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 不会损坏交易。

这里的教训是不要尝试/除了/通过。

【讨论】:

    【解决方案6】:

    我认为在使用 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/dev/ref/databases/#autocommit-mode

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

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

    【讨论】:

      【解决方案7】:

      只使用回滚

      示例代码

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

      【讨论】:

        【解决方案8】:

        如果您在交互式 shell 中遇到此问题并需要快速修复,请执行以下操作:

        from django.db import connection
        connection._rollback()
        

        最初见于this answer

        【讨论】:

          【解决方案9】:

          我在postgres 终端上运行故障事务时遇到了类似的行为。在这之后什么都没有发生,因为database 处于error 的状态。但是,作为一种快速解决方法,如果您有能力避免使用rollback transaction。以下对我有用:

          COMMIT;

          【讨论】:

          • 我在repl中,这正是我正在寻找的答案。
          【解决方案10】:

          我遇到了类似的问题。解决方案是迁移数据库(manage.py syncdbmanage.py schemamigration --auto <table name>,如果您使用南)。

          【讨论】:

            【解决方案11】:

            你只需要运行

            rollback;
            

            在 PostgreSQL 中就是这样!

            【讨论】:

              【解决方案12】:

              在 Flask shell 中,我需要做的只是一个session.rollback() 来解决这个问题。

              【讨论】:

                【解决方案13】:

                我遇到了这个问题,错误是因为错误事务没有正确结束,我找到了事务控制命令herepostgresql_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
                

                【讨论】:

                  【解决方案14】:

                  我在这里遇到了类似的错误。我在这个链接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 的以下查询将不会返回错误。

                  【讨论】:

                  • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
                  【解决方案15】:

                  我也遇到了这个错误,但它掩盖了另一个更相关的错误消息,代码试图在 100 个字符的列中存储一个 125 个字符的字符串:

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

                  我必须调试代码才能显示上述消息,否则会显示

                  DatabaseError: current transaction is aborted
                  

                  【讨论】:

                    【解决方案16】:

                    作为对@priestc 和@Sebastian 的回应,如果你这样做会怎样?

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

                    我刚刚尝试了这段代码,它似乎可以工作,默默地失败而不必关心任何可能的错误,并且在查询良好时工作。

                    【讨论】:

                      【解决方案17】:

                      我相信@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()保留为提取方法仍然很方便,以防在需要特定处理时需要手动使用它,而通用装饰器处理还不够。

                      【讨论】:

                        【解决方案18】:

                        这对我来说是非常奇怪的行为。我很惊讶没有人想到保存点。在我的代码中,查询失败是预期的行为:

                        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
                        

                        【讨论】:

                          【解决方案19】:

                          我正在使用 python 包 psycopg2,但在查询时出现此错误。 我一直只运行查询,然后运行执行功能,但是当我重新运行连接时(如下所示),它解决了问题。所以重新运行脚本上方的内容,即连接,因为正如上面有人所说,我认为它失去了连接或不同步或其他什么。

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

                          【讨论】:

                          • 浪费了将近一个小时,才意识到重新启动内核(不确定是否需要重新启动内核)并重新运行所有单元对我来说都是如此。
                          • 很高兴我能帮上忙!很高兴知道重新启动内核也可以!
                          【解决方案20】:

                          这是一个错误的 sql 执行问题,它不允许其他查询执行,直到前一个查询被挂起/回滚。

                          在PgAdmin4-4.24中有一个回滚选项,可以试试这个。

                          【讨论】:

                            【解决方案21】:

                            您可以通过“set_isolation_level(0)”禁用事务

                            【讨论】:

                              猜你喜欢
                              • 2011-01-13
                              • 2013-08-04
                              • 2012-05-11
                              • 2016-12-11
                              • 1970-01-01
                              • 2011-12-06
                              • 2013-10-25
                              • 1970-01-01
                              相关资源
                              最近更新 更多