Nie. CouchDB używa modelu „optymistycznej współbieżności”. Mówiąc najprościej, oznacza to po prostu, że wysyłasz wersję dokumentu wraz z aktualizacją, a CouchDB odrzuca zmianę, jeśli aktualna wersja dokumentu nie odpowiada temu, co wysłałeś.
To naprawdę zwodniczo proste. Możesz zmienić ramy wielu normalnych scenariuszy opartych na transakcjach dla CouchDB. Jednak podczas nauki CouchDB musisz wyrzucić swoją wiedzę o domenie RDBMS. Pomocne jest podejście do problemów z wyższego poziomu, zamiast próbować dopasować Couch do świata opartego na SQL.
Śledzenie zapasów
Problem, który nakreśliłeś, to przede wszystkim problem z zapasami. Jeśli masz dokument opisujący towar, który zawiera pole „Dostępna ilość”, możesz rozwiązać następujące problemy związane ze współbieżnością:
- Pobierz dokument, zanotuj
_rev
właściwość, którą przesyła CouchDB
- Zmniejsz pole ilości, jeśli jest większe od zera
- Odeślij zaktualizowany dokument, korzystając z
_rev
właściwości
- Jeśli numer
_rev
pasuje do aktualnie zapisanego numeru, gotowe!
- Jeśli występuje konflikt (kiedy
_rev
nie pasuje), pobierz najnowszą wersję dokumentu
W tym przypadku należy przemyśleć dwa możliwe scenariusze awarii. Jeśli najnowsza wersja dokumentu zawiera liczbę 0, postępujesz z nią tak, jak w przypadku systemu RDBMS i ostrzegasz użytkownika, że nie może faktycznie kupić tego, co chciał kupić. Jeśli najnowsza wersja dokumentu zawiera liczbę większą niż 0, po prostu powtórz operację ze zaktualizowanymi danymi i zacznij od początku. To zmusza cię do wykonania nieco więcej pracy niż RDBMS i może być trochę irytujące, jeśli występują częste, sprzeczne aktualizacje.
Odpowiedź, której właśnie udzieliłem, zakłada, że zamierzasz robić rzeczy w CouchDB w taki sam sposób, jak w RDBMS. Mogę podejść do tego problemu nieco inaczej:
Zacząłbym od dokumentu „produktu głównego”, który zawiera wszystkie dane deskryptora (nazwa, zdjęcie, opis, cena itp.). Następnie dodałbym dokument „kwitu inwentaryzacyjnego” dla każdej konkretnej instancji z polami product_key
i claimed_by
. Jeśli sprzedajesz model młota i masz ich 20 do sprzedania, możesz mieć dokumenty z kluczami, takimi jak hammer-1
:hammer-2
itd, aby reprezentować każdą dostępną młotek.
Następnie utworzyłbym widok, który daje mi listę dostępnych młotków z funkcją zmniejszania, która pozwala mi zobaczyć „sumę”. Są one całkowicie poza mankietem, ale powinny dać ci wyobrażenie o tym, jak wyglądałby widok roboczy.
Mapa
function(doc)
{
if (doc.type == 'inventory_ticket' && doc.claimed_by == null ) {
emit(doc.product_key, { 'inventory_ticket' :doc.id, '_rev' : doc._rev });
}
}
To daje mi listę dostępnych „biletów” według klucza produktu. Mógłbym złapać ich grupę, gdy ktoś chce kupić młotek, a następnie iterować, wysyłając aktualizacje (używając id
i_rev
), aż z powodzeniem zdobędę jeden (wcześniej zgłoszone bilety spowodują błąd aktualizacji).
Zmniejszyć
function (keys, values, combine) {
return values.length;
}
Ta funkcja redukcji po prostu zwraca całkowitą liczbę nieodebranych inventory_ticket
elementów, dzięki czemu można określić, ile „młotków” jest dostępnych do zakupu.
Ostrzeżenia
To rozwiązanie reprezentuje około 3,5 minuty całkowitego myślenia nad konkretnym problemem, który przedstawiłeś. Mogą istnieć lepsze sposoby na zrobienie tego! To powiedziawszy, znacznie zmniejsza liczbę konfliktów aktualizacji i ogranicza potrzebę reagowania na konflikt za pomocą nowej aktualizacji. W tym modelu wielu użytkowników nie będzie próbowało zmieniać danych w głównym wpisie produktu. W najgorszym przypadku wielu użytkowników będzie próbowało odebrać jeden bilet, a jeśli złapałeś kilka z nich z widoku, po prostu przejdź do następnego biletu i spróbuj ponownie.
Źródła: https://wiki.apache.org/couchdb/Frequently_asked_questions#How_do_I_use_transactions_with_CouchDB.3F