Нет. CouchDB использует модель «оптимистичного параллелизма». Проще говоря, это просто означает, что вы отправляете версию документа вместе со своим обновлением, и CouchDB отклоняет изменение, если текущая версия документа не соответствует отправленной вами.
На самом деле это обманчиво просто. Вы можете переосмыслить многие обычные сценарии на основе транзакций для CouchDB. Тем не менее, при изучении CouchDB вам нужно как бы выбросить свои знания в области СУБД. Полезно подходить к проблемам с более высокого уровня, а не пытаться приспособить Couch к миру, основанному на SQL.
Отслеживание инвентаря
Обозначенная вами проблема в первую очередь связана с инвентаризацией. Если у вас есть документ, описывающий элемент, и он включает поле для «доступного количества», вы можете решить проблемы параллелизма следующим образом:
- Получите документ, обратите внимание на
_rev
свойство, которое CouchDB отправляет вместе
- Уменьшите значение поля количества, если оно больше нуля
- Отправьте обновленный документ обратно, используя
_rev
свойство
- Если
_rev
совпадает с текущим сохраненным номером, готово!
- Если есть конфликт (когда
_rev
не совпадает), получите самую новую версию документа
В этом случае следует подумать о двух возможных сценариях сбоя. Если количество в самой последней версии документа равно 0, вы обрабатываете ее так же, как и в РСУБД, и предупреждаете пользователя, что он фактически не может купить то, что хотел купить. Если последняя версия документа имеет количество больше 0, вы просто повторяете операцию с обновленными данными и начинаете с самого начала. Это заставляет вас выполнять немного больше работы, чем это сделала бы РСУБД, и может немного раздражать, если есть частые конфликтующие обновления.
Итак, ответ, который я только что дал, предполагает, что вы собираетесь делать что-то в CouchDB почти так же, как в РСУБД. Я мог бы подойти к этой проблеме несколько иначе:
Я бы начал с основного документа продукта, который включает все данные дескриптора (имя, изображение, описание, цену и т. Д.). Затем я бы добавил документ «инвентарный билет» для каждого конкретного экземпляра с полями для product_key
и claimed_by
. Если вы продаете модель молотка, и у вас есть 20 штук на продажу, у вас могут быть документы с ключами, такими как hammer-1
, hammer-2
и т.д., для представления каждого доступного молотка.
Затем я создал представление, которое дает мне список доступных молотков с функцией уменьшения, которая позволяет мне видеть «общее». Они полностью сняты с манжеты, но должны дать вам представление о том, как будет выглядеть рабочий вид.
карта
function(doc)
{
if (doc.type == 'inventory_ticket' && doc.claimed_by == null ) {
emit(doc.product_key, { 'inventory_ticket' :doc.id, '_rev' : doc._rev });
}
}
Это дает мне список доступных «билетов» по ключам продукта. Я мог бы взять группу из них, когда кто-то хочет купить молоток, а затем итеративно отправлять обновления (используя id
и _rev
), пока я не востребую один (ранее заявленные билеты приведут к ошибке обновления).
Уменьшить
function (keys, values, combine) {
return values.length;
}
Эта функция сокращения просто возвращает общее количество невостребованных inventory_ticket
предметов, поэтому вы можете определить, сколько «молотков» доступно для покупки.
Предостережения
Это решение представляет собой примерно 3,5 минуты на обдумывание конкретной проблемы, которую вы представили. Могут быть способы сделать это лучше! Тем не менее, это значительно снижает количество конфликтующих обновлений и снижает необходимость реагировать на конфликт с помощью нового обновления. В соответствии с этой моделью у вас не будет нескольких пользователей, пытающихся изменить данные в первичной записи продукта. В самом худшем случае у вас будет несколько пользователей, пытающихся потребовать один билет, и если вы захватили несколько из них, вы просто переходите к следующему билету и повторите попытку.
Ссылка: https://wiki.apache.org/couchdb/Frequent_asked_questions#How_do_I_use_transactions_with_CouchDB.3F