消息有很多错误:
"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"
从python-psycopg更改为python-psycopg2作为Django项目的数据库引擎。
代码保持不变,只是不知道这些错误来自何处。
conn.rollback()
(其中conn是您的连接对象)将清除错误,以便您可以运行其他查询
消息有很多错误:
"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"
从python-psycopg更改为python-psycopg2作为Django项目的数据库引擎。
代码保持不变,只是不知道这些错误来自何处。
conn.rollback()
(其中conn是您的连接对象)将清除错误,以便您可以运行其他查询
Answers:
当查询产生错误并且您尝试运行另一个查询而不先回滚事务时,这就是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文档
IntegrityError
而不是基类DatabaseError
?
因此,我遇到了同样的问题。我在这里遇到的问题是我的数据库未正确同步。简单的问题似乎总是引起最大的忧虑。
要在终端的应用程序目录中同步django db,请输入:
$ python manage.py syncdb
编辑:请注意,如果您使用的是django-south,则运行'$ python manage.py migration'命令也可以解决此问题。
祝您编码愉快!
python manage.py migrate <app>
...为所有应用程序修复了类似问题。
django-south
-该migrate
命令未内置于Django中。
在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时,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,
}
}
我不确定是否有重要的性能考虑因素(或任何其他类型的考虑因素)。
在postgres
终端上运行有故障的事务时,我遇到了类似的行为。此后什么都没有发生,因为database
处于的状态error
。但是,如果可以避免的话,只是快速解决方法rollback transaction
。以下对我有用:
COMMIT;
我有silimar问题。解决的办法是迁移数据库(manage.py syncdb
或者manage.py schemamigration --auto <table name>
如果您使用南方)。
我也刚遇到这个错误,但是它掩盖了另一个更相关的错误消息,其中代码试图将125个字符的字符串存储在100个字符的列中:
DatabaseError: value too long for type character varying(100)
我必须调试代码才能显示以上消息,否则它将显示
DatabaseError: current transaction is aborted
我相信@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
我已经遇到了这个问题,由于错误交易尚未正确结束,因此出现错误,我在这里找到了postgresql_transactions
Transaction Control命令
交易控制
以下命令用于控制交易
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