Opened 17 years ago
Closed 13 years ago
#6669 closed Uncategorized (fixed)
@transaction.commit_on_success does not rollback when it should
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | transaction, commit |
Cc: | Shai Berger, bhuztez@…, k@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I am using PostgresSQL and have a problem with code like this:
@transaction.commit_on_success def create_system_user(): user = User.objects.create_user(username='system', password='iamr00t', email='root@SITENAME.com') UserProfile.objects.create(user=user) try: create_system_user() except: pass try: create_system_user() except: pass print User.objects.all()
the above code will give:
psycopg2.ProgrammingError: current transaction is aborted, commands ignored until end of transaction block
I have determined that adding a
transaction.rollback()
before the
print User.objects.all()
will allow the user list to be printed correctly.
Looking at the django code, I see:
except Exception, e: if is_dirty(): rollback() raise
in commit_on_success. My guess is that is_dirty() does not take into consideration that an error in PostgresSQL will require a rollback before further work can continue.
Attachments (2)
Change History (14)
comment:1 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
follow-up: 4 comment:2 by , 16 years ago
comment:3 by , 14 years ago
I hit this problem too. Is this the intended behavior? It seems other people have hit this- http://www.mail-archive.com/django-users@googlegroups.com/msg99702.html
comment:4 by , 14 years ago
Replying to myself:
Could this be related to #9964 ?
It seems so; the patch which I uploaded there seems to fix this one too. If the patch is accepted, it may be adivsable to add to tests/regression_tests/transaction_regress/tests.py
(a file created in that patch) the following lines:
def test_6669(self): from django.contrib.auth.models import User @transaction.commit_on_success def create_system_user(): user = User.objects.create_user(username='system', password='iamr00t', email='root@SITENAME.com') Mod.objects.create(fld=user.id) try: create_system_user() except: pass try: create_system_user() except: pass print User.objects.all()
comment:5 by , 14 years ago
Cc: | added |
---|
comment:6 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:7 by , 13 years ago
Cc: | added |
---|---|
Easy pickings: | unset |
Resolution: | fixed |
Severity: | → Normal |
Status: | closed → reopened |
Type: | → Uncategorized |
UI/UX: | unset |
I use Django 1.3.1, but still have to rollback
>>> import django >>> django.get_version() '1.3.1' >>> from django.conf import settings >>> settings.DATABASES['default']['ENGINE'] 'django.db.backends.postgresql_psycopg2' >>> from django.db import transaction >>> from django.contrib.auth.models import User >>> @transaction.commit_on_success ... def create_system_user(): ... user = User.objects.create_user(username='system', password='iamr00t', email='root@SITENAME.com') ... >>> create_system_user() >>> create_system_user() Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/lib/python2.7/site-packages/django/db/transaction.py", line 217, in inner res = func(*args, **kwargs) File "<console>", line 3, in create_system_user File "/usr/lib/python2.7/site-packages/django/contrib/auth/models.py", line 136, in create_user user.save(using=self._db) File "/usr/lib/python2.7/site-packages/django/db/models/base.py", line 460, in save self.save_base(using=using, force_insert=force_insert, force_update=force_update) File "/usr/lib/python2.7/site-packages/django/db/models/base.py", line 553, in save_base result = manager._insert(values, return_id=update_pk, using=using) File "/usr/lib/python2.7/site-packages/django/db/models/manager.py", line 195, in _insert return insert_query(self.model, values, **kwargs) File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 1436, in insert_query return query.get_compiler(using=using).execute_sql(return_id) File "/usr/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 791, in execute_sql cursor = super(SQLInsertCompiler, self).execute_sql(None) File "/usr/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 735, in execute_sql cursor.execute(sql, params) File "/usr/lib/python2.7/site-packages/django/db/backends/util.py", line 34, in execute return self.cursor.execute(sql, params) File "/usr/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 44, in execute return self.cursor.execute(query, args) IntegrityError: duplicate key value violates unique constraint "auth_user_username_key" DETAIL: Key (username)=(system) already exists. >>> User.objects.all() Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 69, in __repr__ data = list(self[:REPR_OUTPUT_SIZE + 1]) File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 84, in __len__ self._result_cache.extend(self._iter) File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 273, in iterator for row in compiler.results_iter(): File "/usr/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 680, in results_iter for rows in self.execute_sql(MULTI): File "/usr/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 735, in execute_sql cursor.execute(sql, params) File "/usr/lib/python2.7/site-packages/django/db/backends/util.py", line 34, in execute return self.cursor.execute(sql, params) File "/usr/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 44, in execute return self.cursor.execute(query, args) DatabaseError: current transaction is aborted, commands ignored until end of transaction block >>> transaction.rollback() >>> User.objects.all() [<User: system>]
comment:9 by , 13 years ago
Cc: | added |
---|
Am seeing this problem with Django 1.3.1, and a non-IntegrityError exception in a view (wrapped with commit_on_success); an object created early on in the view is left in the database, after an error later in the view.
comment:10 by , 13 years ago
Needs tests: | set |
---|
I guess this might be related to the settings.DEBUG state. When DEBUG is False, The CursorWrapper is setting the transaction dirty and the behaviour is correct. However, it seems that CursorDebugWrapper is not setting the transaction dirty (__getattr__
is not called as the execute method does exist on the class), hence the rollback does not happen in the decorator.
comment:11 by , 13 years ago
Has patch: | set |
---|---|
Needs tests: | unset |
Could this be related to #9964 ?