web-dev-qa-db-ger.com

Möglichkeit, dass doppelte Mongo-Objekt-IDs in zwei verschiedenen Sammlungen generiert werden?

Kann dieselbe Mongo ObjectId für ein Dokument in zwei verschiedenen Sammlungen generiert werden? Mir ist klar, dass es definitiv sehr unwahrscheinlich ist, aber ist es möglich?

Ohne zu genau zu werden, frage ich, dass wir mit einer Anwendung, an der ich arbeite, öffentliche Profile von gewählten Funktionären zeigen, von denen wir hoffen, dass sie zu vollwertigen Nutzern unserer Website werden. Wir haben getrennte Sammlungen für Benutzer und gewählte Amtsträger, die derzeit nicht Mitglieder unserer Website sind. Es gibt verschiedene andere Dokumente mit verschiedenen Daten zu den gewählten Amtsträgern, die alle der Person zugeordnet sind, die ihre gewählte offizielle Objekt-ID verwendet.

Nach dem Erstellen des Kontos markieren wir weiterhin die Daten, die dem gewählten Beamten zugeordnet sind. Sie sind jedoch jetzt auch Teil der Benutzersammlung mit einer entsprechenden Benutzer-ObjectId, um ihr Profil Interaktionen mit unserer Anwendung zuzuordnen.

Wir haben vor einigen Monaten damit begonnen, unsere Anwendung von MySql auf Mongo zu konvertieren. Während des Übergangs speichern wir die alte MySql-ID für beide Datentypen und beginnen nun, die ausgewählte offizielle Mongo-Objekt-ID in den Benutzern zu speichern Dokument, um es den gewählten offiziellen Daten zuzuordnen.

Ich habe darüber nachgedacht, nur die neue Benutzer-ObjectId als die zuvor gewählte offizielle ObjectId anzugeben, um die Dinge zu vereinfachen, wollte aber sicherstellen, dass es nicht möglich ist, mit einer vorhandenen Benutzer-ObjectId zu kollidieren.

Vielen Dank für Ihren Einblick.

Bearbeiten: Kurz nach dem Posten dieser Frage stellte ich fest, dass meine vorgeschlagene Lösung keine sehr gute Idee war. Es wäre besser, nur das aktuelle Schema beizubehalten, das wir haben, und nur auf die gewählte offizielle '_id' im Benutzerdokument zu verweisen.

164
Anthony Jack

kurze Antwort

Um nur eine direkte Antwort auf Ihre erste Frage zu geben: JA, wenn Sie die BSON-Objekt-ID-Generierung verwenden, werdenfür die meisten Treiberdie IDs mit ziemlicher Sicherheit in allen Sammlungen eindeutig sein . Weiter unten erfahren Sie, was "mit ziemlicher Sicherheit" bedeutet.

lange Antwort

Es ist sehr wahrscheinlich, dass die von Mongo DB-Treibern generierten BSON-Objekt-IDs in allen Sammlungen eindeutig sind. Dies liegt hauptsächlich an den letzten 3 Bytes der ID, diefür die meisten Treiberüber einen statischen Inkrementierungszähler generiert wird. Dieser Zähler ist sammlungsunabhängig. es ist global. Der Java Treiber verwendet zum Beispiel eine zufällig initialisierte, statische AtomicInteger.

Warum sagen sie in den Mongo-Dokumenten, dass die IDs "höchstwahrscheinlich" eindeutig sind, anstatt direkt zu sagen, dass sie eindeutig sein WERDEN? Drei Möglichkeiten können auftreten, wenn Sie keine eindeutige ID erhalten (bitte teilen Sie mir mit, wenn weitere vorhanden sind):

Denken Sie vor dieser Diskussion daran, dass die BSON-Objekt-ID besteht aus:

[4 Bytes Sekunden seit Epoche, 3 Bytes Maschinen-Hash, 2 Bytes Prozess-ID, 3 Bytes Zähler]

Hier sind die drei Möglichkeiten, damit Sie selbst beurteilen können, wie wahrscheinlich es ist, dass Sie betrogen werden:

1) Zählerüberlauf: Der Zähler enthält 3 Bytes. Wenn Sie zufällig mehr als 16.777.216 (2 ^ 24) Dokumente in einer Sekunde auf demselben Computer in demselben Prozess einfügen, können Sie die inkrementierenden Zählerbytes überlaufen und zwei Objekt-IDs erhalten, die sich dieselbe Zeit und denselben Computer teilen , Prozess- und Zählerwerte.

2) Zähler nicht inkrementieren: Einige Mongo-Treiber verwenden Zufallszahlen anstelle von inkrementierten Zahlen für die Zählerbytes. In diesen Fällen besteht eine Chance von 1/16.777.216, eine nicht eindeutige ID zu generieren, jedoch nur, wenn diese beiden IDs in derselben Sekunde generiert werden (dh bevor der Zeitabschnitt der ID auf die nächste Sekunde aktualisiert wird) Maschine, im gleichen Prozess.

3) Maschine und Prozess Hash auf die gleichen Werte. Die Werte für Computer-ID und Prozess-ID werden möglicherweise in einem höchst unwahrscheinlichen Szenario denselben Werten für zwei verschiedene Computer zugeordnet. Wenn dies der Fall ist und gleichzeitig die beiden Leistungsindikatoren auf den beiden verschiedenen Computern in derselben Sekunde denselben Wert generieren, erhalten Sie eine doppelte ID.

Dies sind die drei Szenarien, auf die Sie achten sollten. Szenario 1 und 3 scheinen sehr unwahrscheinlich, und Szenario 2 ist völlig vermeidbar, wenn Sie den richtigen Treiber verwenden. Sie müssen die Quelle des Treibers überprüfen, um sicherzugehen.

293
Raj Advani

ObjectIds werden clientseitig ähnlich wie UUID generiert, haben jedoch einige bessere Eigenschaften für die Speicherung in einer Datenbank, z. B. die grobe Erhöhung der Reihenfolge und die kostenlose Codierung der Erstellungszeit. Der Schlüssel für Ihren Anwendungsfall ist, dass sie so konzipiert sind, dass sie mit hoher Wahrscheinlichkeit eine Eindeutigkeit gewährleisten, auch wenn sie auf verschiedenen Maschinen generiert werden.

Wenn Sie sich nun allgemein auf das Feld _id beziehen, ist keine Eindeutigkeit für alle Auflistungen erforderlich, sodass die Wiederverwendung der alten _id sicher ist. Wenn Sie beispielsweise zwei Sammlungen haben, colors und fruits, können beide gleichzeitig ein Objekt wie {_id: 'orange'}.

Wenn Sie mehr darüber erfahren möchten, wie ObjectIds erstellt werden, finden Sie hier die Spezifikation: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification

13
mstearn

Falls jemand Probleme mit doppelten Mongo ObjectIDs hat, sollten Sie wissen, dass es trotz der Unwahrscheinlichkeit von Dups in Mongo möglich ist, doppelte _id's mit PHP in Mongo zu generieren.

Der Anwendungsfall, in dem dies für mich regelmäßig passiert ist, ist, wenn ich eine Schleife durch einen Datensatz durchführe und versuche, die Daten in eine Sammlung einzufügen.

Das Array, das die Injektionsdaten enthält, muss bei jeder Iteration explizit zurückgesetzt werden - auch wenn Sie den Wert _id nicht angeben. Aus irgendeinem Grund fügt der INSERT-Prozess die Mongo-ID dem Array hinzu, als wäre sie eine globale Variable (auch wenn das Array keinen globalen Gültigkeitsbereich hat). Dies kann sich auf Sie auswirken, selbst wenn Sie die Einfügung in einem separaten Funktionsaufruf aufrufen, bei dem Sie normalerweise erwarten würden, dass die Werte des Arrays nicht auf der aufrufenden Funktion verbleiben.

Hierfür gibt es drei Lösungen:

  1. Sie können das Feld _id aus dem Array unset()
  2. Sie können das gesamte Array mit array() jedes Mal neu initialisieren, wenn Sie Ihren Datensatz durchlaufen
  3. Sie können den _id-Wert explizit selbst definieren (wobei Sie darauf achten müssen, dass Sie selbst keine Dups generieren).

Ich vermute, dass dies ein Fehler in der PHP Schnittstelle ist und nicht so sehr ein Problem mit Mongo, aber wenn Sie auf dieses Problem stoßen, deaktivieren Sie einfach die _id und Sie sollten in Ordnung sein.

11
DenverMatt