¿Qué significaba realmente que MongoDB no era compatible con ACID antes de v4?

226

No soy un experto en bases de datos y no tengo experiencia en informática, así que tengan paciencia conmigo. Quiero saber los tipos de cosas negativas del mundo real que pueden suceder si usa una versión anterior de MongoDB anterior a la v4 , que no era compatible con ACID . Esto se aplica a cualquier base de datos no compatible con ACID.

Entiendo que MongoDB puede realizar operaciones atómicas , pero que no "admiten el bloqueo tradicional y las transacciones complejas", principalmente por razones de rendimiento. También entiendo la importancia de las transacciones de la base de datos, y el ejemplo de cuando su base de datos es para un banco, y está actualizando varios registros que todos deben estar sincronizados, desea que la transacción vuelva al estado inicial si hay un corte de energía, por lo que el crédito equivale a la compra, etc.

Pero cuando entro en conversaciones sobre MongoDB, aquellos de nosotros que no conocemos los detalles técnicos de cómo se implementan realmente las bases de datos, comenzamos a arrojar declaraciones como:

MongoDB es mucho más rápido que MySQL y Postgres, pero hay una pequeña posibilidad, como 1 en un millón, de que "no se guardará correctamente".

Esa parte "no se guardará correctamente" se refiere a esta comprensión: si hay un corte de energía en el momento en que está escribiendo en MongoDB, existe la posibilidad de un registro en particular (digamos que está rastreando páginas vistas en documentos con 10 atributos cada uno), que uno de los documentos solo guardó 5 de los atributos ... lo que significa que con el tiempo sus contadores de visitas a la página estarán "ligeramente" apagados. Nunca sabrás por cuánto, sabes que serán 99.999% correctos, pero no 100%. Esto se debe a que, a menos que específicamente haya hecho de esto una operación atómica mongodb , no se garantiza que la operación haya sido atómica.

Entonces mi pregunta es, ¿cuál es la interpretación correcta de cuándo y por qué MongoDB no puede "guardar correctamente"? ¿Qué partes de ACID no satisface, y bajo qué circunstancias, y cómo sabe cuándo ese 0.001% de sus datos está apagado? ¿No se puede arreglar esto de alguna manera? Si no, esto parece significar que no debería almacenar cosas como su userstabla en MongoDB, porque un registro podría no guardarse. Pero, de nuevo, ese usuario de 1 / 1,000,000 podría necesitar "intentar registrarse nuevamente", ¿no?

Solo estoy buscando tal vez una lista de cuándo / por qué suceden cosas negativas con una base de datos no compatible con ACID como MongoDB, e idealmente si hay una solución alternativa estándar (como ejecutar un trabajo en segundo plano para limpiar datos, o solo usar SQL para esto, etc.) .

Lance Pollard
fuente

Respuestas:

133

Una cosa que pierde con MongoDB son las transacciones de varias colecciones (tablas). Los modificadores atómicos en MongoDB solo pueden funcionar en un solo documento.

Si necesita eliminar un artículo del inventario y agregarlo al pedido de alguien al mismo tiempo, no puede. A menos que esas dos cosas, inventario y pedidos, existan en el mismo documento (que probablemente no existan).

Encontré este mismo problema en una aplicación en la que estoy trabajando y tenía dos posibles soluciones para elegir:

1) Estructura tus documentos lo mejor que puedas y usa modificadores atómicos lo mejor que puedas y para el bit restante, usa un proceso en segundo plano para limpiar los registros que pueden estar fuera de sincronización. Por ejemplo, elimino artículos del inventario y los agrego a una matriz de inventario reservado del mismo documento usando modificadores atómicos.

Esto me permite saber siempre que los artículos NO están disponibles en el inventario (porque están reservados por un cliente). Cuando el cliente se retira, elimino los elementos del Inventario reservado. No es una transacción estándar y, dado que el cliente podría abandonar el carrito, necesito un proceso en segundo plano para buscar y encontrar carritos abandonados y mover el inventario reservado nuevamente al grupo de inventario disponible.

Obviamente, esto es menos que ideal, pero es la única parte de una gran aplicación en la que mongodb no se ajusta perfectamente a la necesidad. Además, funciona perfectamente hasta ahora. Esto puede no ser posible para muchos escenarios, pero debido a la estructura del documento que estoy usando, se adapta bien.

2) Use una base de datos transaccional junto con MongoDB. Es común usar MySQL para proporcionar transacciones para las cosas que los necesitan absolutamente mientras se deja que MongoDB (o cualquier otro NoSQL) haga lo que hace mejor.

Si mi solución del n. ° 1 no funciona a largo plazo, investigaré más a fondo para combinar MongoDB con MySQL, pero por ahora el n. ° 1 se adapta bien a mis necesidades.

Bryan Migliorisi
fuente
27
" Los modificadores atómicos en MongoDB solo pueden funcionar en una sola colección " => Creo que quiso decir "en un solo documento ".
Assylias 05 de
2
Excelente información, generalmente una excelente respuesta con la excepción de sugerir usar MySQL.
Doug Molineux el
״ Una cosa que pierde con MongoDB son las transacciones de varias colecciones (tablas). Los modificadores atómicos en MongoDB solo pueden funcionar contra un solo documento ״ de mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): "En MongoDB, una operación de escritura es atómica en el nivel de un solo documento, incluso si la operación modifica múltiples documentos incrustados dentro de un solo documento ".
yoav.str
55
La falta de transacciones ACID de documentos múltiples ya no es el caso. MongoDB anunció que vendrán en v4.0. Ver mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik
1
Por ahora, dado que MongoDB 4.0 es compatible con ACID, mongodb.com/transactions con transacciones de documentos múltiples. Echa un vistazo a mongodb.com/blog/post/…
Ratah
134

En realidad, no es correcto que MongoDB no sea compatible con ACID. Por el contrario, MongoDB es compatible con ACID a nivel de documento .

Cualquier actualización de un solo documento es

  • Atómico: se completa por completo o no
  • Consistente: ningún lector verá una actualización "parcialmente aplicada"
  • Aislado: de nuevo, ningún lector verá una lectura "sucia"
  • Duradero: (con la preocupación de escritura apropiada)

Lo que MongoDB no tiene es transacciones , es decir, actualizaciones de documentos múltiples que pueden revertirse y son compatibles con ACID.

Tenga en cuenta que puede crear transacciones sobre las actualizaciones compatibles con ACID en un solo documento, mediante el compromiso de dos fases .

William Z
fuente
3
Tenga en cuenta que las transacciones de confirmaciones de dos fases no son compatibles con ACID. Por alguna razón deduje lo contrario hasta que seguí el enlace.
Justin C
1
Hay algunas dudas sobre la durabilidad de MongoDB distribuido a nivel de documento, independientemente de la configuración de la preocupación de escritura. La herramienta de código abierto Jepsen descubrió que los datos pueden perderse frente a una partición de red incluso con la preocupación de escritura MAYORÍA. Vea el artículo aquí: aphyr.com/posts/284-call-me-maybe-mongodb
jrullmann el
99
Tener ACID al nivel de un solo documento que de alguna manera equivale a un solo registro en RDBMS no es útil en muchos casos. El término de la transacción no se relaciona con una sola tabla, e incluso puede tener un mecanismo de confirmación de dos fases e involucrar varios XAResource, por lo tanto, hacer referencia al documento único como compatible con ACID es algo problemático, en mi humilde opinión.
Yair Zaslavsky
55
De acuerdo con Yair. "Compatible con ACID a nivel de documento" no es un punto de venta. Básicamente significa "no compatible con ACID". ACID nunca tuvo la intención de ser "solo una fila / documento / entidad". Se trata de mantener sus datos consistentes en toda la base de datos.
joshua.paling
34

Una buena explicación está contenida en "Starbucks no utiliza el compromiso de dos fases" .

No se trata de bases de datos NoSQL, pero ilustra el punto de que a veces puede permitirse perder una transacción o tener su base de datos en un estado inconsistente temporalmente.

No lo consideraría algo que necesita ser "arreglado". La solución es usar una base de datos relacional compatible con ACID. Usted elige una alternativa NoSQL cuando su comportamiento cumple con los requisitos de su aplicación.

duffymo
fuente
1
Como cualquier analogía, tiene sus limitaciones. En el software, es fácil crear nuevos Array [Cajeros] y hacer que procesen transacciones sincrónicas cada uno, mientras que el costo real sería ridículamente costoso.
HRJ
16

Creo que otras personas ya dieron buenas respuestas. Sin embargo, me gustaría agregar que hay bases de datos ACID NOSQL (como http://ravendb.net/ ). Por lo tanto, no es solo una decisión NOSQL: no ACID vs Relacional con ACID ...

SubGate
fuente
1
gracias @subGate. ¿Hay alguien por ahí que pueda compartir su experiencia con ravenDB y si realmente cumple con el requisito?
Nir Pengas
12

"no se guardará correctamente" podría significar:

  1. Por defecto, MongoDB no guarda sus cambios en el disco de inmediato. Por lo tanto, existe la posibilidad de que le diga a un usuario "la actualización fue exitosa", se produce un corte de energía y se pierde la actualización. MongoDB proporciona opciones para controlar el nivel de actualización "durabilidad". Puede esperar a que la (s) otra (s) réplica (s) reciban esta actualización (en la memoria), esperar que la escritura ocurra en el archivo de diario local, etc.

  2. No hay actualizaciones "atómicas" fáciles para múltiples colecciones e incluso múltiples documentos en la misma colección. No es un problema en la mayoría de los casos porque se puede eludir con Two Phase Commit , o reestructurar su esquema para que las actualizaciones se realicen en un solo documento. Consulte esta pregunta: Bases de datos de documentos: datos redundantes, referencias, etc. (MongoDB específicamente)

Sergey
fuente
10

A partir de MongoDB v4.0, se admitirán transacciones ACID de varios documentos. A través del aislamiento de instantáneas, las transacciones proporcionarán una vista globalmente coherente de los datos y exigirán la ejecución de todo o nada para mantener la integridad de los datos.

Se sienten como transacciones del mundo relacional, por ejemplo:

with client.start_session() as s:
    s.start_transaction()
    try:
        collection.insert_one(doc1, session=s)
        collection.insert_one(doc2, session=s)
        s.commit_transaction()
    except Exception:
        s.abort_transaction()

Ver https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb

Grigori Melnik
fuente
El primer candidato de lanzamiento de MongoDB4.0 está fuera - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik
5

Lea acerca de las propiedades de ACID para obtener una mejor comprensión.

También en la documentación de MongoDB puede encontrar una pregunta y respuesta .

MongoDB no es compatible con ACID. Lea a continuación para una discusión sobre el cumplimiento de ACID.

  1. MongoDB es Atomic solo a nivel de documento. No cumple con la definición de atómica que conocemos de los sistemas de bases de datos relacionales, en particular el enlace anterior. En este sentido, MongoDB no cumple con la A de ACID.
  2. MongoDB es Cin situ de manera predeterminada. Sin embargo, puede leer desde servidores secundarios en un conjunto de réplicas. Solo puedes tener una consistencia eventual en este caso. Esto es útil si no le importa leer datos ligeramente desactualizados.
  3. MongoDB no garantiza la Isolación (nuevamente según la definición anterior):
  1. Para sistemas con múltiples lectores y escritores concurrentes, MongoDB permitirá a los clientes leer los resultados de una operación de escritura antes de que la operación de escritura regrese.
  2. Si el mongod termina antes de que el diario se confirme, incluso si una escritura regresa con éxito, las consultas pueden haber leído datos que no existirán después de que el mongod se reinicie.

Sin embargo , MongoDB modifica cada documento de forma aislada (para inserciones y actualizaciones); solo a nivel de documento, no en transacciones de varios documentos.

  1. Con respecto a la Durabilidad, puede configurar este comportamiento con la write concernopción, aunque no estoy seguro. Quizás alguien lo sepa mejor.

Creo que se están realizando algunas investigaciones para mover NoSQL hacia restricciones de ACID o similares. Esto es un desafío porque las bases de datos NoSQL suelen ser rápidas (er) y las restricciones de ACID pueden ralentizar significativamente el rendimiento.

Ely
fuente
4

La única razón por la que atomic modifica el trabajo contra una colección única es porque los desarrolladores de mongodb intercambiaron recientemente un bloqueo de base de datos con un bloqueo de escritura de toda la colección. Decidir que la mayor concurrencia aquí valió la pena. En esencia, mongodb es un archivo mapeado en memoria: han delegado la administración de la agrupación de almacenamiento intermedio al subsistema vm de la máquina. Debido a que siempre está en la memoria, pueden escapar con bloqueos muy específicos: solo realizarás operaciones en memoria mientras lo sostienes, lo que será extremadamente rápido. Esto difiere significativamente de un sistema de base de datos tradicional que a veces se ve obligado a realizar E / S mientras mantiene un bloqueo de página o un bloqueo de fila.

joeshmoe
fuente
¿podría explicar por qué esto aumenta la concurrencia? Lo siento si me estoy perdiendo lo obvio aquí.
Batbrat
@batbrat: considere dos clientes que intentan escribir simultáneamente en diferentes colecciones en la misma base de datos. Con un bloqueo de base de datos, uno de los clientes tendrá que esperar a que el otro termine antes de que se pueda escribir. Con un bloqueo de colección, ambos clientes pueden escribir al mismo tiempo. Eso es lo que se entiende por mayor concurrencia. Por supuesto, si ambos clientes intentan escribir en la misma colección, entonces uno tendrá que esperar.
jrullmann
2

"En MongoDB, una operación en un solo documento es atómica": eso es lo que pasó en el pasado

En la nueva versión de MongoDB 4.0 PUEDES:

Sin embargo, para situaciones que requieren atomicidad para actualizaciones de múltiples documentos o consistencia entre lecturas a múltiples documentos, MongoDB brinda la capacidad de realizar transacciones de múltiples documentos contra conjuntos de réplicas. Las transacciones de varios documentos se pueden usar en múltiples operaciones, colecciones, bases de datos y documentos. Las transacciones de documentos múltiples proporcionan una propuesta de "todo o nada". Cuando se confirma una transacción, se guardan todos los cambios de datos realizados en la transacción. Si falla alguna operación en la transacción, la transacción se anula y todos los cambios de datos realizados en la transacción se descartan sin volverse visibles. Hasta que se confirme una transacción, no hay operaciones de escritura en la transacción visibles fuera de la transacción.

Aunque hay pocas limitaciones para cómo y qué operaciones se pueden realizar.

Consulte el Mongo Doc. https://docs.mongodb.com/master/core/transactions/

Misterioso25K
fuente
1

Puede implementar actualizaciones atómicas de varias claves (transacción serializable) en el lado del cliente si su almacenamiento admite la linealización por clave y compara y establece (lo cual es cierto para MongoDB). Este enfoque se utiliza en Google Percolator y en CockroachDB pero nada le impide usarlo con MongoDB.

He creado una visualización paso a paso. de tales transacciones. Espero que te ayude a entenderlos.

Si está de acuerdo con el nivel de aislamiento de lectura comprometida, entonces tiene sentido echar un vistazo a las transacciones RAMP de Peter Bailis. También se pueden implementar para MongoDB en el lado del cliente.

rystsov
fuente