Exception causes next transaction to abort

Bug #1238559 reported by Kasper Dupont on 2013-10-11
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
psycopg2 (Ubuntu)
Undecided
Unassigned

Bug Description

I have a program, which roughly goes like this:

try: do_something()
except: record_error()

Each of do_something and record_error use @commit_on_success to perform a database transaction. If the very first operation performed by do_something raises an IntegrityError, then the transaction in record_error is immediately aborted.

The exception raised by do_something looked like this:
IntegrityError: null value in column "name_of_recently_added_field" violates not-null constraint
That was due to a misconfiguration, and was expected to happpen:

The exception raised by record_error looked like this:
django.db.utils.DatabaseError: current transaction is aborted, commands ignored until end of transaction block
That is not supposed to happen, since the failed transaction was supposed to have been aborted, and a new should have been started.

Both do_something and record_error experience the exception upon calling Model.objects.create(...) on two different models.

ProblemType: Bug
DistroRelease: Ubuntu 12.04
Package: python-psycopg2 2.4.5-1
ProcVersionSignature: Ubuntu 3.2.0-54.82-generic 3.2.50
Uname: Linux 3.2.0-54-generic i686
NonfreeKernelModules: nvidia
ApportVersion: 2.0.1-0ubuntu17.5
Architecture: i386
Date: Fri Oct 11 11:11:20 2013
EcryptfsInUse: Yes
InstallationMedia: Ubuntu 11.04 "Natty Narwhal" - Release i386 (20110427.1)
MarkForUpload: True
SourcePackage: psycopg2
UpgradeStatus: Upgraded to precise on 2012-05-08 (520 days ago)

It turns out this bug can also cause data corruption.

If the exception causing the first transaction to abort is not database related, then the failing transaction is committed. Committing a half completed transaction on an exception is a sure way to violate data integrity.

It appears the problem in both cases is that transactions are marked dirty too late. It is possible to get an exception between the point where the transaction really becomes dirty and the point where the db layer actually marks the transaction dirty. In that case upon exiting @commit_on_success, the transaction is neither committed nor rolled back. Instead it is reused for the next @commit_on_success, and if that commits successfully, the partial transaction is committed.

One way the data corruption can be triggered is through a combination of bug 1238559 and bug 1100758.

I'm starting to wonder if this bug might actually be in the django db layer rather than in psycopg2.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers