Django cache.set (), вызывающий дублируемую ключевую ошибку

Мой сайт Django недавно начал бросать ошибки из моего кода кеширования, и я не могу понять, почему …

Я звоню:

from django.core.cache import cache cache.set('blogentry', some_value) 

И ошибка, которую Django вызывает:

 TransactionManagementError: This code isn't under transaction management 

Но, смотря на журналы базы данных PostgreSQL, похоже, это связано с этой ошибкой:

 STATEMENT: INSERT INTO cache_table (cache_key, value, expires) VALUES (E'blogentry', E'pickled_version_of_some_value', E'2009-07-27 11:10:26') ERROR: duplicate key value violates unique constraint "cache_table_pkey" 

Для жизни я не могу понять, почему Django пытается сделать INSERT вместо UPDATE. Есть предположения?

3 Solutions collect form web for “Django cache.set (), вызывающий дублируемую ключевую ошибку”

Это типичная гонка. Он проверяет, существует ли ключ, который вы вставили; если это не так, это делает вставку, но кто-то другой может вставить ключ между счетчиком и вставкой. Транзакции не мешают этому.

Код, похоже, ожидает этого и пытается справиться с этим, но когда я посмотрел на код для обработки этого случая, я сразу увидел, что он был сломан. Сообщено здесь: http://code.djangoproject.com/ticket/11569

Я настоятельно рекомендую придерживаться бэкэнда memcache.

Код в core / cache / backend / db.py частично читается:

 cursor.execute("SELECT cache_key, expires FROM %s WHERE cache_key = %%s" % self._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" % self._table, [encoded, str(exp), key]) else: cursor.execute("INSERT INTO %s (cache_key, value, expires) VALUES (%%s, %%s, %%s)" % self._table, [key, encoded, str(exp)]) 

Поэтому я бы сказал, что вы делаете INSERT INTO вместо UPDATE, потому что результат оценивается как false. По какой-то причине cursor.fetchone () возвращает 0 строк, если на самом деле там есть.

если вы не можете сломать здесь отладчик, я бы поставил инструкции трассировки в источник, чтобы подтвердить, что это происходит на самом деле.

Я решил эту проблему, создав собственный буферный сервер, переопределив функцию _base_set () и изменив инструкцию INSERT INTO следующим образом. Этот трюк SQL предотвращает появление INSERT в случае, если cache_key уже существует.

 cursor.execute("INSERT INTO %s (cache_key, value, expires) SELECT %%s, %%s, %%s WHERE NOT EXISTS (SELECT 1 FROM %s WHERE cache_key = %%s)" % (table, table), [key, encoded, connections[db].ops.value_to_db_datetime(exp), key]) 
  • Как удалить кавычки из строки для SQL-запроса в Python?
  • Как изменить выбор в поле выбора OpenERP на основе других значений полей?
  • Многопользовательская работа с SQLAlchemy
  • Самый быстрый способ создания нового объекта, только если он еще не существует (SQLAlchemy)
  • Postgresql DROP TABLE не работает
  • Сортировка списка кортежей с учетом локали (шведский заказ)
  • psycopg2 COPY с помощью cursor.copy_from () зависает с большими входами
  • Ошибка сокета Postgresql при запуске Django syncdb (mac OS 10.7.5)
  • Django, ManyToManyField - ProgrammingError: отношение foo_bar не существует. Признается в миграциях, хотя отношение никогда не создается
  • Как я могу объединить соединения с помощью psycopg и gevent?
  • psycopg2 E 'на столе, поле и схеме
  • Python - лучший язык программирования в мире.