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.
This commit is contained in:
parent
faabf3614e
commit
1b12e248ea
|
@ -10,7 +10,7 @@ except ImportError:
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache.backends.base import BaseCache
|
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 import timezone, six
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
|
|
||||||
|
@ -108,19 +108,20 @@ class DatabaseCache(BaseDatabaseCache):
|
||||||
# string, not bytes. Refs #19274.
|
# string, not bytes. Refs #19274.
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
b64encoded = b64encoded.decode('latin1')
|
b64encoded = b64encoded.decode('latin1')
|
||||||
|
try:
|
||||||
|
with transaction.atomic_if_autocommit(using=db):
|
||||||
cursor.execute("SELECT cache_key, expires FROM %s "
|
cursor.execute("SELECT cache_key, expires FROM %s "
|
||||||
"WHERE cache_key = %%s" % table, [key])
|
"WHERE cache_key = %%s" % table, [key])
|
||||||
try:
|
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
if result and (mode == 'set' or
|
exp = connections[db].ops.value_to_db_datetime(exp)
|
||||||
(mode == 'add' and result[1] < now)):
|
if result and (mode == 'set' or (mode == 'add' and result[1] < now)):
|
||||||
cursor.execute("UPDATE %s SET value = %%s, expires = %%s "
|
cursor.execute("UPDATE %s SET value = %%s, expires = %%s "
|
||||||
"WHERE cache_key = %%s" % table,
|
"WHERE cache_key = %%s" % table,
|
||||||
[b64encoded, connections[db].ops.value_to_db_datetime(exp), key])
|
[b64encoded, exp, key])
|
||||||
else:
|
else:
|
||||||
cursor.execute("INSERT INTO %s (cache_key, value, expires) "
|
cursor.execute("INSERT INTO %s (cache_key, value, expires) "
|
||||||
"VALUES (%%s, %%s, %%s)" % table,
|
"VALUES (%%s, %%s, %%s)" % table,
|
||||||
[key, b64encoded, connections[db].ops.value_to_db_datetime(exp)])
|
[key, b64encoded, exp])
|
||||||
except DatabaseError:
|
except DatabaseError:
|
||||||
# To be threadsafe, updates/inserts are allowed to fail silently
|
# To be threadsafe, updates/inserts are allowed to fail silently
|
||||||
return False
|
return False
|
||||||
|
|
Loading…
Reference in New Issue