Разрешение конфликтов в ZODB

Я запускаю параллельные запросы на запись в моей ZODB. У меня есть несколько экземпляров BTree в моей ZODB. Как только сервер получает доступ к тем же объектам внутри такого BTree, я получаю ConflictError для класса IOBucket. Для всех моих базовых классов Django у меня настроен _p_resolveconflict, но я не могу реализовать его для IOBucket, потому что это класс на основе C.

Я сделал более глубокий анализ, но так и не понял, почему он жалуется на класс IOBucket и что в него пишет. Кроме того, какова была бы правильная стратегия для ее решения?

Тысяча благодарностей за любую помощь!


person patroqueeet    schedule 16.08.2012    source источник


Ответы (1)


IOBucket является частью персистентной структуры BTree; он существует, чтобы попытаться уменьшить количество ошибок, связанных с конфликтами, и он действительно пытается разрешать конфликты, где это возможно.

Тем не менее, конфликтов не всегда можно избежать, и вам следует перезапустить транзакцию. В Zope, например, весь запрос повторяется до 5 раз, если поднимается ConflictError. Конфликты — это способ ZODB обрабатывать (надеюсь, редкий) случай, когда два разных запроса пытались изменить одну и ту же структуру данных.

Перезапуск вашей транзакции означает вызов transaction.begin() и повторное применение тех же изменений. .begin() извлечет любые изменения, сделанные другим процессом, и ваша фиксация будет основана на свежих данных.

person Martijn Pieters    schedule 16.08.2012
comment
Уважаемый, я использую django_zodb, где транзакция стартет довольно рано и я бы не стал ее перехватывать. Вчера я обнаружил, что вызов root._p_jar.sync() до изменения и transaction.savepoint после изменения хранилища данных разрешил конфликтную ошибку. хотя я не до конца понял логику. это имеет смысл или я сделал что-то странное? - person patroqueeet; 17.08.2012
comment
еще один вопрос: поэтому было бы целесообразно создать лог, который перехватывает исключение примерно 5 раз, затем ждет несколько мс, а затем повторяет попытку с полной новой транзакцией? если это так. Я имел в виду, что моя транзакция начинается по запросу сервера и заканчивается, когда отображается ответ. тогда это устарело? Так что для моей очень безопасной среды сложные транзакции не будут хорошим подходом с zodb? эти транзакции должны быть больше похожи на ACID? - person patroqueeet; 17.08.2012
comment
@patroqueeet: _p_jar.sync() означает загрузку последних данных (что означает, что теперь вы можете работать с несогласованным состоянием). savepoint — это просто средство сброса изменений на диск (так что освободите память) до момента фиксации. - person Martijn Pieters; 17.08.2012
comment
@patroqueeet: я не знаком с django_zodb; быстрый взгляд на компонент промежуточного программного обеспечения этого пакета действительно показывает, что он не повторяет запрос. Сравните это с пакетом pyramid_tm, где есть возможность повторить попытку. . В идеале промежуточное ПО транзакций django_zodb должно делать то же самое. - person Martijn Pieters; 17.08.2012
comment
@patroqueeet: нет необходимости ждать несколько мс. При возникновении конфликта перезапустите всю транзакцию сразу же с новыми данными, другая транзакция, с которой вы столкнулись, уже завершена. - person Martijn Pieters; 17.08.2012
comment
идеально. это указывает мне именно то, что я искал. Посмотрим на пирамиду_tm, проанализирую обработку конфликтов и добавим ее поверх django_zodb... - person patroqueeet; 17.08.2012