Django

Code

Ticket #5043 (closed: duplicate)

Opened 1 year ago

Last modified 9 months ago

Postgresql transaction error handling is different

Reported by: Nis Jørgensen <nis@superlativ.dk> Assigned to: nobody
Milestone: Component: Database wrapper
Version: SVN Keywords:
Cc: metajack@gmail.com Triage Stage: Design decision needed
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

(Discussion is happening here): http://groups.google.com/group/django-users/browse_thread/thread/8004a40b3c607d08/7b7ed19d276033df

Postgresql does error handling inside transactions differently than mySQL and sqlite. When using the latter two, you can do this inside a transaction:

class MyModel(Model):
    uniquefield = CharField(max_length=200,unique=True)

MyModel.objects.create(uniquefield='Some non-unique value')
try:
    MyModel.objects.create(uniquefield='Some non-unique value')
except:
    MyModel.objects.create(uniquefield='A unique value')

while in postgres the last query will fail as well.

Note that postgresql is by default inside a transaction - ticket #3460 is aimed at fixing this.

I believe the solution is to wrap the "execute" method to generate savepoints when inside a transaction. Something like the following (untested) pseudocode:

def myexecute(self, *args,**kwargs):
    if self.is_in_transaction:
        self.create_save_point(identifier)  
        try: 
            self.execute(*args,**kwargs)
        except DatabaseError,e:
            self.rollback(identifier)
            raise
    else:
        self.execute(*args,**kwargs)

Attachments

Change History

(follow-up: ↓ 2 ) 08/01/07 10:24:46 changed by mir@noris.de

  • status changed from new to closed.
  • needs_better_patch changed.
  • resolution set to duplicate.
  • needs_tests changed.
  • needs_docs changed.

The problem you see is not directly caused by the isolation level, but by the fact that postgresql is not able to continue a transaction once a statement has failed. I consider ticket #3460 the wrong solution, since it basically turns off all transaction support.

Your second block is the better solution.

I close this ticket as a duplicate, though.

(in reply to: ↑ 1 ) 08/01/07 10:31:59 changed by anonymous

Replying to mir@noris.de:

The problem you see is not directly caused by the isolation level, but by the fact that postgresql is not able to continue a transaction once a statement has failed. I consider ticket #3460 the wrong solution, since it basically turns off all transaction support. Your second block is the better solution. I close this ticket as a duplicate, though.

#3460 turns off transaction by default, which is correct. You still get transaction if you explicitly use them (or perhaps I am confusing this with my Twisted patches since they had the same problem). You want singleton queries not inside BEGIN/END/COMMIT pairs, but you want multiple INSERT or DELETE queries inside the pairs. Before the patch you get BEGIN/END/COMMIT pairs on every query no matter what, which is quite inefficient if you have lots of simple selects (which is 80% of what most django apps do).

08/01/07 10:33:10 changed by anonymous

  • cc set to metajack@gmail.com.

08/01/07 15:29:00 changed by Nis Jørgensen <nis@superlativ.dk>

I disagree that this is a duplicate of #3460. This bug is about the behavior of django when in a transaction. 3460 is about whether django is, bu default, in a transaction. So I am reopening the ticket.

I do not have an opinion on whether 3460 should be fixed or not - I am not really sure about the implications of it.

Nis

08/01/07 16:27:12 changed by Nis Jørgensen <nis@superlativ.dk>

  • status changed from closed to reopened.
  • resolution deleted.

08/07/07 05:55:05 changed by mir@noris.de

Nils: please start a thread on django-developers, so that we can settle this.

09/20/07 14:27:37 changed by mir

  • stage changed from Unreviewed to Design decision needed.

Looking at this again, I think Nis is right. savepoints would probably be nice to cope with this.

12/01/07 15:06:25 changed by jacob

  • status changed from reopened to closed.
  • resolution set to duplicate.

This is indeed an issue of transaction isolation -- Postgres deliberately doesn't allow additional statements after a failed one, and if you want to do so you need different transaction handling. As such, this is a duplicate of #6064.


Add/Change #5043 (Postgresql transaction error handling is different)




Change Properties
Action