CouchDB является транзакционной по умолчанию. Каждый документ в couchdb содержит ключ _rev
. Все изменения в документе выполняются в отношении этого ключа _rev
: -
- Получить документ.
- Отправьте его для обновления с использованием свойства _rev.
- Если обновление прошло успешно, вы обновили последний документ документа
- Если обновление не удалось, документ был не последним. Повторите шаги 1-3.
Отъезд this answer by MrKurt для получения более подробного объяснения.
У couchdb recipies есть пример банковского обслуживания, показывающий, как транзакции выполняются в couchdb.
И есть также эта статья atomic bank transfers, которая иллюстрирует транзакции в couchdb.
В любом случае общая тема во всех этих ссылках заключается в том, что если вы будете следовать шаблону couchdb для обновления с _rev
, у вас не может быть несогласованного состояния в вашей базе данных.
Heck, чтобы быть в безопасности, я мог бы даже установить уникальное ограничение на индекс (clientId, filenumber), чтобы гарантировать, что никогда не будет одинакового имени файла, используемого дважды для клиента.
Все документы couchdb уникальны, поскольку поля в двух документах не могут быть одинаковыми. Проверьте view cookbook
Это простой: в базе данных CouchDB каждый документ должен иметь уникальное поле _id. Если вам нужны уникальные значения в базе данных, просто назначьте их в поле _id документа, а CouchDB обеспечит уникальность для вас.
Однако есть одно предостережение: в распределенном случае, когда вы используете более одного узла CouchDB, который принимает запросы на запись, уникальность может быть гарантирована только на узел или вне CouchDB. CouchDB позволит записать два идентичных идентификатора на два разных узла. При репликации CouchDB обнаружит конфликт и соответствующим образом помечает документ.
Редактировать основанный на комментарий
В случае, когда вы хотите, чтобы увеличить поле в одном документе на основе успешной вставки другого документа
Вы могли бы использовать отдельные документы в этом случае. Вы вставляете документ, ожидая ответа на успех. Затем добавьте еще один документ, как
{_id:'some_id','count':1}
С этим вы можете создать карту уменьшить вид, что просто подсчитывает результаты этих документов и у вас есть счетчик обновлений. Все, что вы делаете, это вместо обновления одного документа для обновлений, которые вы вставляете в новый документ, чтобы отразить успешную вставку.
Я всегда заканчиваю случай, когда неудачная вставка файла оставила БД в несогласованном состоянии, особенно с другим клиентом, успешно вставляющим файл в одно и то же время.
Хорошо, так что я уже описал, как вы можете сделать обновления более отдельных документов, но даже при обновлении одного документа вы можете избежать несогласованности, если вы:
- Вставьте новый файл
- Когда CouchDB дает сообщение успеха -> попытка обновления счетчика.
Почему это работает?
Это работает, потому что, когда вы пытаетесь обновить update document
, вы должны поставить строку _rev
. Вы можете думать о _rev
как о локальном состоянии для своего документа. Рассмотрим этот сценарий: -
- Вы читаете документ, который необходимо обновить.
- Вы меняете некоторые поля.
- Между тем другой запрос уже изменил исходный документ. Это означает, что документ теперь имеет новый
- Но вы запрашиваете couchdb для обновления документа с
_rev
, который является stale
, который вы читаете на шаге 1.
- Couchdb генерирует исключение.
- Вы снова читаете документ, чтобы получить последние
_rev
и попытайтесь его обновить.
Поэтому, если вы сделаете это, вам всегда придется обновлять последнюю версию документа. Надеюсь, это немного улучшит ситуацию.
Примечание:
Как отметил Даниил _rev
правил не распространяются на насыпные обновления.
Я уже читал о двухфазных фиксациях, но я до сих пор не вижу, как это применимо здесь. Если у меня есть один поток, я вижу, что он работает, но если у меня есть несколько потоков, у меня нет гарантии на атомарность - это нить # 2 может быть полностью исполнена до того, как нить # 1 будет завершена, а если первый не удастся, второй будет успешным, номер файла/счетчик будет неправильным. Если я не понимаю, как правильно выполнить двухфазную фиксацию (я так не думаю). –