Exception causes next transaction to abort
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
psycopg2 (Ubuntu) |
Expired
|
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_
That was due to a misconfiguration, and was expected to happpen:
The exception raised by record_error looked like this:
django.
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.
ProblemType: Bug
DistroRelease: Ubuntu 12.04
Package: python-psycopg2 2.4.5-1
ProcVersionSign
Uname: Linux 3.2.0-54-generic i686
NonfreeKernelMo
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.