¿Posibilidad de que se generen Mongo ObjectId duplicados en dos colecciones diferentes?

Resuelto Anthony Jack asked hace 13 años • 4 respuestas

¿Es posible generar exactamente el mismo Mongo ObjectId para un documento en dos colecciones diferentes? Me doy cuenta de que definitivamente es muy improbable, pero ¿es posible?

Sin ser demasiado específico, la razón por la que pregunto es que con una aplicación en la que estoy trabajando mostramos perfiles públicos de funcionarios electos que esperamos convertir en usuarios de pleno derecho de nuestro sitio. Tenemos colecciones separadas para usuarios y funcionarios electos que actualmente no son miembros de nuestro sitio. Hay varios otros documentos que contienen diversos datos sobre los funcionarios electos que se relacionan con la persona que utiliza su ObjectId del funcionario electo.

Después de crear la cuenta, aún resaltamos los datos asociados al funcionario electo, pero ahora también forman parte de la colección de usuarios con un ObjectId de usuario correspondiente para asignar su perfil a las interacciones con nuestra aplicación.

Comenzamos a convertir nuestra aplicación de MySql a Mongo hace unos meses y, mientras estamos en la transición, almacenamos la identificación MySql heredada para ambos tipos de datos y ahora también estamos comenzando a almacenar el ObjectId oficial elegido de Mongo en los usuarios. documento para mapear los datos del funcionario electo.

Estaba pensando en especificar el nuevo ObjectId de usuario como el ObjectId oficial elegido anteriormente para simplificar las cosas, pero quería asegurarme de que no fuera posible tener una colisión con ningún ObjectId de usuario existente.

Gracias por tu conocimiento.

Editar: Poco después de publicar esta pregunta, me di cuenta de que la solución que propuse no era una muy buena idea. Sería mejor simplemente mantener el esquema actual que tenemos y simplemente vincularlo al funcionario electo '_id' en el documento de los usuarios.

Anthony Jack avatar Jan 13 '11 12:01 Anthony Jack
Aceptado

Respuesta corta

Solo para agregar una respuesta directa a su pregunta inicial: SÍ, si utiliza la generación de ID de objeto BSON, para la mayoría de los controladores es casi seguro que las ID serán únicas en todas las colecciones. Consulte a continuación lo que significa "casi con certeza".

Respuesta larga

Es muy probable que los ID de objeto BSON generados por los controladores Mongo DB sean únicos en todas las colecciones. Esto se debe principalmente a los últimos 3 bytes del ID, que para la mayoría de los controladores se genera mediante un contador incremental estático. Ese contador es independiente de la colección; es mundial. El controlador Java, por ejemplo, utiliza un AtomicInteger estático inicializado aleatoriamente.

Entonces, ¿por qué, en los documentos de Mongo, dicen que es "altamente probable" que las identificaciones sean únicas, en lugar de decir directamente que SERÁN únicas? Pueden ocurrir tres posibilidades en las que no obtendrá una identificación única (avíseme si hay más):

Antes de esta discusión, recuerde que el ID de objeto BSON consta de:

[4 bytes segundos desde la época, 3 bytes de hash de máquina, 2 bytes de ID de proceso, 3 bytes de contador]

Aquí tienes las tres posibilidades, para que juzgues por ti mismo la probabilidad de que te engañen:

1) Desbordamiento del contador: hay 3 bytes en el contador. Si inserta más de 16,777,216 (2^24) documentos en un solo segundo, en la misma máquina, en el mismo proceso, entonces puede desbordar los bytes del contador incremental y terminar con dos ID de objeto que comparten el mismo tiempo, máquina. , proceso y valores de contador.

2) Contador no incremental: algunos controladores Mongo usan números aleatorios en lugar de números incrementales para los bytes del contador. En estos casos, existe una probabilidad de 1/16.777.216 de generar una ID no única, pero sólo si esas dos ID se generan en el mismo segundo (es decir, antes de que la sección de tiempo de la ID se actualice al siguiente segundo), en el mismo máquina, en el mismo proceso.

3) Máquina y proceso de hash con los mismos valores. Los valores de ID de máquina e ID de proceso pueden, en algún escenario muy improbable, asignarse a los mismos valores para dos máquinas diferentes. Si esto ocurre, y al mismo tiempo los dos contadores en las dos máquinas diferentes, durante el mismo segundo, generan el mismo valor, entonces terminará con una identificación duplicada.

Estos son los tres escenarios a tener en cuenta. Los escenarios 1 y 3 parecen muy improbables, y el escenario 2 es totalmente evitable si se utiliza el controlador adecuado. Tendrás que verificar la fuente del controlador para estar seguro.

Raj Advani avatar Apr 17 '2011 16:04 Raj Advani

En caso de que alguien tenga problemas con los ObjectID duplicados de Mongo, debe saber que a pesar de la improbabilidad de que se produzcan duplicados en Mongo, es posible generar _id duplicados con PHP en Mongo.

El caso de uso en el que esto me ha sucedido con regularidad es cuando recorro un conjunto de datos e intento inyectar los datos en una colección.

La matriz que contiene los datos de inyección debe restablecerse explícitamente en cada iteración, incluso si no especifica el valor _id. Por alguna razón, el proceso INSERT agrega Mongo _id a la matriz como si fuera una variable global (incluso si la matriz no tiene alcance global). Esto puede afectarlo incluso si está llamando a la inserción en una llamada de función separada donde normalmente esperaría que los valores de la matriz no persistan en la función que llama.

Hay tres soluciones para esto:

  1. Puedes unset()el campo _id de la matriz
  2. Puede reinicializar toda la matriz array()cada vez que recorre su conjunto de datos
  3. Puede definir explícitamente el valor _id usted mismo (teniendo cuidado de definirlo de tal manera que no genere dups usted mismo).

Supongo que esto es un error en la interfaz de PHP, y no tanto un problema con Mongo, pero si te encuentras con este problema, simplemente desarma el _id y todo estará bien.

DenverMatt avatar Apr 16 '2012 23:04 DenverMatt