Нет. CouchDB использует модель «оптимистичного параллелизма». Проще говоря, это просто означает, что вы отправляете версию документа вместе с вашим обновлением, и CouchDB отклоняет изменение, если текущая версия документа не соответствует отправленной вами.
Это обманчиво просто, правда. Вы можете переосмыслить многие обычные сценарии на основе транзакций для CouchDB. Тем не менее, при изучении CouchDB вам все равно нужно отбросить свои знания в области СУБД. Полезно подходить к проблемам с более высокого уровня, а не пытаться превратить Couch в мир, основанный на SQL.
Отслеживание инвентаря
Обозначенная вами проблема - это проблема инвентаря. Если у вас есть документ, описывающий товар, и он содержит поле для «доступного количества», вы можете справиться с такими проблемами параллелизма:
- Получите документ, обратите внимание на свойство
_rev
, которое CouchDB отправляет вместе
- Уменьшить поле количества, если оно больше нуля
- Отправьте обновленный документ обратно, используя свойство
_rev
- Если
_rev
соответствует текущему сохраненному номеру, сделайте!
- Если есть конфликт (когда
_rev
не совпадает), получить самую новую версию документа
В этом случае есть два возможных сценария отказа, о которых стоит подумать. Если последняя версия документа имеет количество 0, вы обрабатываете ее так же, как в СУБД, и предупреждаете пользователя о том, что он на самом деле не может купить то, что он хотел купить. Если последняя версия документа имеет количество больше 0, вы просто повторяете операцию с обновленными данными и начинаете сначала. Это заставляет вас выполнять немного больше работы, чем это делает СУБД, и может стать немного раздражающим при частых конфликтующих обновлениях.
Теперь, ответ, который я только что дал, предполагает, что вы будете делать вещи в CouchDB почти так же, как в RDBMS. Я мог бы подойти к этой проблеме немного по-другому:
Я бы начал с документа «основной продукт», который включает все данные дескриптора (имя, изображение, описание, цена и т. Д.). Затем я бы добавил документ «инвентарный билет» для каждого конкретного экземпляра с полями для 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/Frequently_asked_questions#How_do_I_use_transactions_with_CouchDB.3F