diff options
| author | Aymeric Augustin <aymeric.augustin@m4x.org> | 2013-03-11 22:16:37 +0100 |
|---|---|---|
| committer | Aymeric Augustin <aymeric.augustin@m4x.org> | 2013-03-11 22:19:48 +0100 |
| commit | 1b12e248ea556789e994caa8d3849f4de6a9096e (patch) | |
| tree | 3035b64e537bf71ba1d1c3944159b97c609cc412 | |
| parent | faabf3614e27c2b616bf4730272fafa9627652d8 (diff) | |
Fixed #11569 -- Wrapped DatabaseCache._base_set in an atomic block.
The atomic block provides a clean rollback to a savepoint on failed writes.
The ticket reported a race condition which I don't know how to test.
| -rw-r--r-- | django/core/cache/backends/db.py | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py index 53d7f4d22a..f18b05db2f 100644 --- a/django/core/cache/backends/db.py +++ b/django/core/cache/backends/db.py @@ -10,7 +10,7 @@ except ImportError: from django.conf import settings from django.core.cache.backends.base import BaseCache -from django.db import connections, router, DatabaseError +from django.db import connections, transaction, router, DatabaseError from django.utils import timezone, six from django.utils.encoding import force_bytes @@ -26,7 +26,7 @@ class Options(object): self.model_name = 'cacheentry' self.verbose_name = 'cache entry' self.verbose_name_plural = 'cache entries' - self.object_name = 'CacheEntry' + self.object_name = 'CacheEntry' self.abstract = False self.managed = True self.proxy = False @@ -108,19 +108,20 @@ class DatabaseCache(BaseDatabaseCache): # string, not bytes. Refs #19274. if six.PY3: b64encoded = b64encoded.decode('latin1') - cursor.execute("SELECT cache_key, expires FROM %s " - "WHERE cache_key = %%s" % table, [key]) try: - result = cursor.fetchone() - if result and (mode == 'set' or - (mode == 'add' and result[1] < now)): - cursor.execute("UPDATE %s SET value = %%s, expires = %%s " - "WHERE cache_key = %%s" % table, - [b64encoded, connections[db].ops.value_to_db_datetime(exp), key]) - else: - cursor.execute("INSERT INTO %s (cache_key, value, expires) " - "VALUES (%%s, %%s, %%s)" % table, - [key, b64encoded, connections[db].ops.value_to_db_datetime(exp)]) + with transaction.atomic_if_autocommit(using=db): + cursor.execute("SELECT cache_key, expires FROM %s " + "WHERE cache_key = %%s" % table, [key]) + result = cursor.fetchone() + exp = connections[db].ops.value_to_db_datetime(exp) + if result and (mode == 'set' or (mode == 'add' and result[1] < now)): + cursor.execute("UPDATE %s SET value = %%s, expires = %%s " + "WHERE cache_key = %%s" % table, + [b64encoded, exp, key]) + else: + cursor.execute("INSERT INTO %s (cache_key, value, expires) " + "VALUES (%%s, %%s, %%s)" % table, + [key, b64encoded, exp]) except DatabaseError: # To be threadsafe, updates/inserts are allowed to fail silently return False |
