Nein. CouchDB verwendet ein "optimistisches Parallelitäts" -Modell. Im einfachsten Sinne bedeutet dies nur, dass Sie eine Dokumentversion zusammen mit Ihrem Update senden und CouchDB die Änderung ablehnt, wenn die aktuelle Dokumentversion nicht mit der von Ihnen gesendeten übereinstimmt.
Es ist wirklich täuschend einfach. Sie können viele normale transaktionsbasierte Szenarien für CouchDB neu gestalten. Sie müssen jedoch Ihr RDBMS-Domänenwissen irgendwie wegwerfen, wenn Sie CouchDB lernen. Es ist hilfreich, Probleme von einer höheren Ebene aus anzugehen, anstatt zu versuchen, Couch an eine SQL-basierte Welt anzupassen.
Inventar verfolgen
Das von Ihnen beschriebene Problem ist in erster Linie ein Inventarproblem. Wenn Sie ein Dokument haben, das einen Artikel beschreibt und ein Feld für "verfügbare Menge" enthält, können Sie Probleme mit der Parallelität wie folgt behandeln:
- Rufen Sie das Dokument ab und notieren Sie sich die
_rev
Eigenschaft, die CouchDB mitsendet
- Dekrementieren Sie das Mengenfeld, wenn es größer als Null ist
- Senden Sie das aktualisierte Dokument mithilfe der
_rev
Eigenschaft zurück
- Wenn das
_rev
mit der aktuell gespeicherten Nummer übereinstimmt, fertig!
- Wenn ein Konflikt vorliegt (wenn er
_rev
nicht übereinstimmt), rufen Sie die neueste Dokumentversion ab
In diesem Fall müssen zwei mögliche Fehlerszenarien berücksichtigt werden. Wenn die neueste Dokumentversion eine Menge von 0 hat, behandeln Sie diese wie in einem RDBMS und warnen den Benutzer, dass er nicht kaufen kann, was er kaufen möchte. Wenn die neueste Dokumentversion eine Menge größer als 0 hat, wiederholen Sie einfach den Vorgang mit den aktualisierten Daten und beginnen wieder am Anfang. Dies zwingt Sie dazu, etwas mehr Arbeit zu leisten als ein RDBMS und kann bei häufigen, widersprüchlichen Updates etwas ärgerlich werden.
Die Antwort, die ich gerade gegeben habe, setzt voraus, dass Sie die Dinge in CouchDB genauso machen wie in einem RDBMS. Ich könnte dieses Problem etwas anders angehen:
Ich würde mit einem "Master-Produkt" -Dokument beginnen, das alle Deskriptordaten (Name, Bild, Beschreibung, Preis usw.) enthält. Dann würde ich für jede spezifische Instanz ein "Inventarticket" -Dokument mit Feldern für product_key
und hinzufügen claimed_by
. Wenn Sie ein Modell von Hammer verkaufen, und haben 20 von ihnen zu verkaufen, könnten Sie Dokumente mit Tasten wie hammer-1
, hammer-2
usw., um jeden verfügbaren Hammer darzustellen.
Dann würde ich eine Ansicht erstellen, die mir eine Liste der verfügbaren Hämmer mit einer Reduzierungsfunktion gibt, mit der ich eine "Summe" sehen kann. Diese sind völlig aus der Manschette, sollten Ihnen aber eine Vorstellung davon geben, wie eine Arbeitsansicht aussehen würde.
Karte
function(doc)
{
if (doc.type == 'inventory_ticket' && doc.claimed_by == null ) {
emit(doc.product_key, { 'inventory_ticket' :doc.id, '_rev' : doc._rev });
}
}
Dies gibt mir eine Liste der verfügbaren "Tickets" nach Produktschlüssel. Ich könnte mir eine Gruppe davon schnappen, wenn jemand einen Hammer kaufen möchte, und dann durch das Senden von Updates (mit id
und _rev
) iterieren, bis ich eines erfolgreich beanspruche (zuvor beanspruchte Tickets führen zu einem Update-Fehler).
Reduzieren
function (keys, values, combine) {
return values.length;
}
Diese Reduzierungsfunktion gibt einfach die Gesamtzahl der nicht beanspruchten inventory_ticket
Artikel zurück, sodass Sie feststellen können, wie viele "Hämmer" zum Kauf verfügbar sind.
Vorsichtsmaßnahmen
Diese Lösung entspricht ungefähr 3,5 Minuten Gesamtdenken für das von Ihnen vorgestellte Problem. Es gibt vielleicht bessere Möglichkeiten, dies zu tun! Das heißt, es reduziert widersprüchliche Updates erheblich und verringert die Notwendigkeit, auf einen Konflikt mit einem neuen Update zu reagieren. Bei diesem Modell werden nicht mehrere Benutzer versuchen, Daten im primären Produkteintrag zu ändern. Im schlimmsten Fall versuchen mehrere Benutzer, ein einzelnes Ticket zu beanspruchen. Wenn Sie mehrere davon aus Ihrer Sicht ausgewählt haben, fahren Sie einfach mit dem nächsten Ticket fort und versuchen es erneut.
Referenz: https://wiki.apache.org/couchdb/Frequently_asked_questions#How_do_I_use_transactions_with_CouchDB.3F