我收到了很多错误的信息:
"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"
作为Django项目的数据库引擎,从python-psycopg改为python-psycopg2。
代码保持不变,只是不知道这些错误来自哪里。
我收到了很多错误的信息:
"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"
作为Django项目的数据库引擎,从python-psycopg改为python-psycopg2。
代码保持不变,只是不知道这些错误来自哪里。
当前回答
我认为在使用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,
}
}
我不确定是否有重要的性能考虑因素(或任何其他类型)。
其他回答
作为对@priestc和@Sebastian的回应,如果你也这样做呢?
try:
conn.commit()
except:
pass
cursor.execute( sql )
try:
return cursor.fetchall()
except:
conn.commit()
return None
我刚刚尝试了这段代码,它似乎工作,失败无声,而不必关心任何可能的错误,并在查询良好时工作。
这种行为对我来说很奇怪。我很惊讶没有人想到保存点。在我的代码中,查询失败是预期的行为:
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
根据我的经验,这些错误是这样发生的:
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
第二个查询没有问题,但是由于捕获了真正的错误,第二个查询将引发(信息量少得多的)错误。
edit:这只发生在except子句捕捉到IntegrityError(或任何其他低级数据库异常)时,如果你捕捉到像DoesNotExist这样的错误,这个错误将不会出现,因为DoesNotExist不会破坏事务。
这里的教训是不要尝试/except/pass。
我也有这个错误,但它掩盖了另一个更相关的错误消息,代码试图在100个字符的列中存储125个字符的字符串:
DatabaseError: value too long for type character varying(100)
我必须调试代码才能显示上面的消息,否则就会显示
DatabaseError: current transaction is aborted
我认为在使用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,
}
}
我不确定是否有重要的性能考虑因素(或任何其他类型)。