Garantías de aislamiento
Lectura no confirmada
Dependiendo del problema de lectura, los clientes pueden ver los resultados de las escrituras antes de que se realicen. durable:
Independientemente del problema de escritura de un escritor, otros clientes que utilizan
"local"La"available"preocupación de lectura o puede ver el resultado de una operación de escritura antes de que la operación de escritura sea reconocida por el cliente emisor.Los clientes que utilizan
"local"o"available"como nivel de consistencia de lectura pueden leer datos que pueden ser posteriormente revertidos durante las conmutaciones por error del set de réplicas.
Para las operaciones en una transacción multi-documento, cuando una transacción se confirma, todos los cambios de datos realizados en la transacción se guardan y son visibles fuera de la transacción. Es decir, una transacción no realizará la confirmación de algunos de sus cambios mientras revierte otros.
Hasta que se produzca la confirmación de una transacción, los cambios de datos realizados en la transacción no son visibles fuera de la transacción.
Sin embargo, cuando una transacción se guarda en múltiples fragmentos, no todas las operaciones de lectura externas necesitan esperar a que el resultado de la transacción confirmada sea visible en todos los fragmentos. Por ejemplo, si se confirma una transacción y la escritura 1 es visible en el fragmento A, pero la escritura 2 aún no es visible en el fragmento B, una lectura externa con el nivel de consistencia de lectura "local" puede leer los resultados de la escritura 1 sin ver la escritura 2.
La lectura no confirmada es el nivel de aislamiento por defecto y se aplica tanto a instancias autónomas mongod como a sets de réplicas y clústeres particionados.
Lectura no confirmada y atomicidad de documento único
Las operaciones de guardar son atómicas con respecto a un único documento; es decir, si una operación de guardar está actualizando varios campos en el documento, una operación de lectura nunca verá el documento con solo algunos de los campos actualizados. Sin embargo, aunque un cliente puede no ver un documento parcialmente actualizado, la lectura no confirmada significa que las operaciones de lectura concurrentes aún pueden ver el documento actualizado antes de que los cambios se hagan durables.
Con una instancia mongod autónoma, un conjunto de operaciones de lectura y escritura en un único documento es serializable. Con un set de réplicas, un conjunto de operaciones de lectura y escritura en un solo documento es serializable solo en ausencia de un rollback.
Lectura no confirmada y escritura de múltiples documentos
Cuando una sola operación de guardado (p. ej. db.collection.updateMany()) modifica múltiples documentos; la modificación de cada documento es atómica, pero la operación en su conjunto no es atómica.
Al realizar Operaciones de guardado multidocumento, ya sea a través de una sola Operación de guardado o de múltiples Operaciones de guardado, otras Operaciones pueden intercalarse.
Para situaciones que requieren atomicidad de las lecturas y escrituras en varios documentos (en una sola colección o en varias), MongoDB admite transacciones distribuidas, incluidas las transacciones en sets de réplica y clústeres fragmentados.
Para obtener más información, consulta transacciones
Importante
En la mayoría de los casos, una transacción distribuida incurre en un costo de rendimiento mayor que las escrituras de documentos individuales, y la disponibilidad de transacciones distribuidas no debería ser un sustituto para un diseño de esquema efectivo. Para muchos casos, el modelo de datos desnormalizado (documento incrustado y matrices) seguirá siendo óptimo para tus datos y casos de uso. Es decir, en muchos casos, modelar tus datos de forma adecuada minimizará la necesidad de transacciones distribuidas.
Para consideraciones adicionales sobre el uso de transacciones (como el límite de tiempo de ejecución y el límite de tamaño del oplog), consulta también las consideraciones de producción.
Sin aislar las operaciones de escritura de múltiples documentos, MongoDB muestra el siguiente comportamiento:
Operaciones de lectura no puntuales en el tiempo. Supongamos que una operación de lectura comienza en el tiempo t 1 y comienza a leer documentos. Luego, una operación de escritura confirma una actualización de uno de los documentos en algún momento posterior t 2. El lector puede ver la versión actualizada del documento y, por lo tanto, no ve una snapshot de los datos en un punto en el tiempo.
Operaciones no serializables. Supongamos que una operación de lectura lee un documento d 1 en el momento t 1 y que una operación de escritura actualiza d 1 en algún momento posterior t 3. Esto introduce una dependencia de lectura-escritura tal que, si las operaciones se serializaran, la operación de lectura debe preceder a la operación de escritura. Pero también supongamos que la operación de escritura actualiza el documento d 2 en el momento t 2 y que la operación de lectura posteriormente lee d 2 en un momento posterior t 4. Esto introduce una dependencia de escritura-lectura que, en cambio, requeriría que la operación de lectura viniera después de la operación de escritura en un cronograma serializable. Existe un ciclo de dependencia que hace imposible la serializabilidad.
Las lecturas pueden omitir documentos coincidentes que se actualicen durante el transcurso de la operación de lectura.
Snapshot de cursor
Los cursores de MongoDB pueden devolver el mismo documento más de una vez en algunas situaciones. A medida que un cursor devuelve documentos, otras operaciones pueden intercalarse con la query. Si una de estas operaciones cambia el campo indexado en el índice utilizado por la query, entonces el cursor podría devolver el mismo documento más de una vez.
Las queries que utilizan índices únicos pueden, en algunos casos, devolver valores duplicados. Si un cursor que utiliza un índice único se entrelaza con un borrado y una inserción de documentos que comparten el mismo valor único, el cursor puede devolver el mismo valor único dos veces desde documentos diferentes.
Se debe considerar la posibilidad de utilizar el aislamiento de lectura. Para aprender más, se puede consultar nivel de consistencia de lectura "snapshot".
Escrituras monotónicas
MongoDB proporciona garantías de escrituras monotónicas, por defecto, para instancias mongod autónomas y sets de réplicas.
Para escrituras monotónicas y clústeres particionados, consultar Coherencia causal.
Las escrituras que no modifican ningún documento se conocen como escrituras de no operación noop. Escrituras de no-operación:
Ocurre si el filtro para escritura no coincide con ningún documento, o los documentos coincidentes no cambian después de aplicar la escritura.
No aumente el valor de optime.
Se devuelve
WriteResult.nModifiedigual a0, lo que indica que la operación de escritura no modificó ningún documento.
Para asegurar la monotonicidad con escrituras sin operación, se debe utilizar garantías de coherencia causal. Para todas las demás escrituras, las garantías de monotonicidad se describen en las siguientes secciones.
Orden en tiempo real
Para las operaciones de lectura y escritura en el primario, emitir operaciones de lectura con nivel de consistencia de lectura "linearizable" y operaciones de escritura con nivel de confirmación de escritura "majority" permite que múltiples hilos realicen lecturas y escrituras en un solo documento en tiempo real como si un solo hilo realizara estas operaciones; es decir, el cronograma correspondiente para estas lecturas y escrituras se considera linealizable.
Coherencia causal
Si una operación depende lógicamente de una operación anterior, existe una relación causal entre las operaciones. Por ejemplo, una operación de escritura que borra todos los documentos basándose en una condición especificada y una operación de lectura posterior que verifica la operación de escritura tienen una relación causal.
Con sesiones causalmente coherentes, MongoDB ejecuta operaciones causales en un orden que respeta sus relaciones causales, y los clientes observan resultados que son coherentes con las relaciones causales.
Sesiones de cliente y garantías de coherencia causal
Para proporcionar coherencia causal, MongoDB activa la coherencia causal en las sesiones de los clientes. Una sesión con coherencia causal indica que la secuencia asociada de operaciones de lectura con nivel de consistencia de lectura "majority" y operaciones de escritura con nivel de confirmación de escritura "majority" tienen una relación causal que se refleja en su orden.
Las aplicaciones deben asegurarse de que solo un hilo a la vez ejecute estas operaciones en una sesión de cliente.
Para operaciones causalmente relacionadas:
Un cliente inicia una sesión de cliente.
Importante
Las sesiones de cliente solo garantizan la coherencia causal para:
Operaciones de lectura con
"majority"; es decir, los datos devueltos han sido reconocidos por la mayoría de los nodos del set de réplicas y son durables.Operaciones de escritura con nivel de confirmación de escritura (write concern)
"majority"; es decir, las operaciones de escritura que solicitan reconocimiento de que la operación se ha aplicado a la mayoría de los miembros votantes del set de réplicas.
Para aprender más sobre la coherencia causal y las preocupaciones de lectura y los niveles de confirmación de escritura, se puede consultar Coherencia causal y nivel de consistencia de lectura y nivel de confirmación de escritura.
A medida que el cliente emite una secuencia de operaciones de lectura con un nivel de consistencia de lectura
"majority"y operaciones de escritura (con nivel de confirmación de escritura)"majority", el cliente incluye la información de la sesión con cada operación.Para cada operación de lectura con nivel de consistencia de lectura
"majority"y operación de escritura con nivel de confirmación de escritura"majority"asociadas a la sesión, MongoDB devuelve el optime y el tiempo del clúster, incluso si la operación falla. La sesión del cliente rastrea el optime y el tiempo del clúster.Nota
MongoDB no devuelve el optime ni el tiempo del clúster para las operaciones de escritura no reconocidas (
w: 0). Las escrituras no confirmadas no implican ninguna relación causal.Aunque MongoDB devuelve el tiempo de operación y el tiempo de clúster para las operaciones de lectura y las operaciones de escritura reconocidas en una sesión de cliente, solo las operaciones de lectura con un nivel de consistencia de lectura
"majority"y operaciones de escritura con un nivel de confirmación de escritura"majority"pueden garantizar la coherencia causal. Para aprender más, se puede consultar coherencia causal y nivel de consistencia de lectura y nivel de confirmación de escritura.La sesión de cliente asociada rastrea estos dos campos temporales.
Nota
Las operaciones pueden mantener la coherencia causal a través de diferentes sesiones. Los MongoDB drivers y
mongoshproporcionan los métodos para avanzar el optime y el tiempo de clúster para una sesión de cliente. Así, un cliente puede adelantar el tiempo del clúster y el optime de una sesión de cliente para que sea coherente con las operaciones de otra sesión de cliente.
Garantías de coherencia causal
La siguiente tabla enumera las garantías de coherencia causal proporcionadas por sesiones causalmente consistentes para operaciones de lectura con nivel de consistencia de lectura "majority" y operaciones de escritura con nivel de confirmación de escritura "majority".
Garantías | Descripción |
|---|---|
Leer las escrituras | Las operaciones de lectura reflejan los resultados de las operaciones de escritura que las preceden. |
Lecturas monotónicas | Las operaciones de lectura no devuelven resultados que correspondan a un estado anterior de los datos que el de una operación de lectura precedente. Por ejemplo, si en una sesión:
entonces la lectura 2 no puede devolver resultados de escritura 1. |
Escrituras monotónicas | Las operaciones de escritura que deben preceder a otras operaciones de escritura se ejecutan antes que esas otras operaciones de escritura. Por ejemplo, si la escritura 1 debe preceder a la escritura 2 en una sesión, el estado de los datos en el momento de la escritura 2 debe reflejar el estado de los datos después de la escritura 1. Otras operaciones de escritura pueden intercalarse entre la escritura 1 y la escritura 2, pero la escritura 2 no puede ocurrir antes de la escritura 1. |
Las escrituras siguen a las lecturas | Las operaciones de escritura que deben realizarse después de las operaciones de lectura se ejecutan tras completar dichas operaciones de lectura. Es decir, el estado de los datos en el momento de la escritura debe incorporar el estado de los datos de las operaciones de lectura anteriores. |
preferencia de lectura
Estas garantías se mantienen en todos los nodos de la implementación de MongoDB. Por ejemplo, si en una sesión causalmente coherente, se emite una escritura con nivel de confirmación de escritura "majority" seguida de una lectura que lee de un secundario (es decir, preferencia de lectura secondary) con nivel de consistencia de lectura "majority", la operación de lectura reflejará el estado de la base de datos después de la operación de escritura.
Aislamiento
Las operaciones dentro de una sesión con coherencia causal no están aisladas de las operaciones fuera de la sesión. Si una operación de escritura concurrente se intercala entre las operaciones de escritura y lectura de la sesión, la operación de lectura de la sesión puede devolver resultados que reflejan una operación de escritura que ocurrió después de la operación de escritura de la sesión.
Controladores de MongoDB
Tip
Las aplicaciones deben asegurarse de que solo un hilo a la vez ejecute estas operaciones en una sesión de cliente.
Los clientes requieren controladores de MongoDB actualizados para MongoDB 3.6 o versiones posteriores:
Java 3.6+ Python 3.6+ C 1.9+ Go 1.8+ | C# 2.5+ Node 3.0+ Ruby 2.5+ Rust 2.1+ Swift 1.2+ | Perl 2.0+ PHPC 1.4+ Scala 2.2+ C++ 3.6.6+ |
Ejemplos
Importante
Las sesiones con coherencia causal solo pueden garantizar la consistencia causal para las lecturas con "majority" nivel de consistencia de lectura y las escrituras con "majority" nivel de confirmación de escritura.
Considere una colección items que mantenga los datos actuales e históricos de varios elementos. Solo los datos históricos tienen una fecha end no nula. Si el valor sku de un elemento cambia, el documento con el valor sku anterior debe actualizarse con la fecha end, tras lo cual se inserta el nuevo documento con el valor sku actual. El cliente puede utilizar una sesión con coherencia causal para asegurar que la actualización se realice antes de la inserción.
➤ Se puede usar el menú desplegable Seleccionar su lenguaje en la parte superior derecha para establecer el lenguaje de este ejemplo.
/* Use a causally-consistent session to run some operations. */ wc = mongoc_write_concern_new (); mongoc_write_concern_set_wmajority (wc, 1000); mongoc_collection_set_write_concern (coll, wc); rc = mongoc_read_concern_new (); mongoc_read_concern_set_level (rc, MONGOC_READ_CONCERN_LEVEL_MAJORITY); mongoc_collection_set_read_concern (coll, rc); session_opts = mongoc_session_opts_new (); mongoc_session_opts_set_causal_consistency (session_opts, true); session1 = mongoc_client_start_session (client, session_opts, &error); if (!session1) { fprintf (stderr, "couldn't start session: %s\n", error.message); goto cleanup; } /* Run an update_one with our causally-consistent session. */ update_opts = bson_new (); res = mongoc_client_session_append (session1, update_opts, &error); if (!res) { fprintf (stderr, "couldn't add session to opts: %s\n", error.message); goto cleanup; } query = BCON_NEW ("sku", "111"); update = BCON_NEW ("$set", "{", "end", BCON_DATE_TIME (bson_get_monotonic_time ()), "}"); res = mongoc_collection_update_one (coll, query, update, update_opts, NULL, /* reply */ &error); if (!res) { fprintf (stderr, "update failed: %s\n", error.message); goto cleanup; } /* Run an insert with our causally-consistent session */ insert_opts = bson_new (); res = mongoc_client_session_append (session1, insert_opts, &error); if (!res) { fprintf (stderr, "couldn't add session to opts: %s\n", error.message); goto cleanup; } insert = BCON_NEW ("sku", "nuts-111", "name", "Pecans", "start", BCON_DATE_TIME (bson_get_monotonic_time ())); res = mongoc_collection_insert_one (coll, insert, insert_opts, NULL, &error); if (!res) { fprintf (stderr, "insert failed: %s\n", error.message); goto cleanup; }
using (var session1 = client.StartSession(new ClientSessionOptions { CausalConsistency = true })) { var currentDate = DateTime.UtcNow.Date; var items = client.GetDatabase( "test", new MongoDatabaseSettings { ReadConcern = ReadConcern.Majority, WriteConcern = new WriteConcern( WriteConcern.WMode.Majority, TimeSpan.FromMilliseconds(1000)) }) .GetCollection<BsonDocument>("items"); items.UpdateOne(session1, Builders<BsonDocument>.Filter.And( Builders<BsonDocument>.Filter.Eq("sku", "111"), Builders<BsonDocument>.Filter.Eq("end", BsonNull.Value)), Builders<BsonDocument>.Update.Set("end", currentDate)); items.InsertOne(session1, new BsonDocument { {"sku", "nuts-111"}, {"name", "Pecans"}, {"start", currentDate} }); }
// Example 1: Use a causally consistent session to ensure that the update occurs before the insert. ClientSession session1 = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); Date currentDate = new Date(); MongoCollection<Document> items = client.getDatabase("test") .withReadConcern(ReadConcern.MAJORITY) .withWriteConcern(WriteConcern.MAJORITY.withWTimeout(1000, TimeUnit.MILLISECONDS)) .getCollection("test"); items.updateOne(session1, eq("sku", "111"), set("end", currentDate)); Document document = new Document("sku", "nuts-111") .append("name", "Pecans") .append("start", currentDate); items.insertOne(session1, document);
async with await client.start_session(causal_consistency=True) as s1: current_date = datetime.datetime.today() items = client.get_database( "test", read_concern=ReadConcern("majority"), write_concern=WriteConcern("majority", wtimeout=1000), ).items await items.update_one( {"sku": "111", "end": None}, {"$set": {"end": current_date}}, session=s1 ) await items.insert_one( {"sku": "nuts-111", "name": "Pecans", "start": current_date}, session=s1 )
$items = $client->selectDatabase( 'test', [ 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::MAJORITY), 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000), ], )->items; $s1 = $client->startSession( ['causalConsistency' => true], ); $currentDate = new \MongoDB\BSON\UTCDateTime(); $items->updateOne( ['sku' => '111', 'end' => ['$exists' => false]], ['$set' => ['end' => $currentDate]], ['session' => $s1], ); $items->insertOne( ['sku' => '111-nuts', 'name' => 'Pecans', 'start' => $currentDate], ['session' => $s1], );
with client.start_session(causal_consistency=True) as s1: current_date = datetime.datetime.today() items = client.get_database( "test", read_concern=ReadConcern("majority"), write_concern=WriteConcern("majority", wtimeout=1000), ).items items.update_one( {"sku": "111", "end": None}, {"$set": {"end": current_date}}, session=s1 ) items.insert_one( {"sku": "nuts-111", "name": "Pecans", "start": current_date}, session=s1 )
let s1 = client1.startSession(options: ClientSessionOptions(causalConsistency: true)) let currentDate = Date() var dbOptions = MongoDatabaseOptions( readConcern: .majority, writeConcern: try .majority(wtimeoutMS: 1000) ) let items = client1.db("test", options: dbOptions).collection("items") let result1 = items.updateOne( filter: ["sku": "111", "end": .null], update: ["$set": ["end": .datetime(currentDate)]], session: s1 ).flatMap { _ in items.insertOne(["sku": "nuts-111", "name": "Pecans", "start": .datetime(currentDate)], session: s1) }
let s1 = client1.startSession(options: ClientSessionOptions(causalConsistency: true)) let currentDate = Date() var dbOptions = MongoDatabaseOptions( readConcern: .majority, writeConcern: try .majority(wtimeoutMS: 1000) ) let items = client1.db("test", options: dbOptions).collection("items") try items.updateOne( filter: ["sku": "111", "end": .null], update: ["$set": ["end": .datetime(currentDate)]], session: s1 ) try items.insertOne(["sku": "nuts-111", "name": "Pecans", "start": .datetime(currentDate)], session: s1)
Si otro cliente necesita leer todos los valores actuales de sku, puede adelantar el tiempo del clúster y el optime al de la otra sesión para asegurar que este cliente sea causalmente coherente con la otra sesión y lea después de las dos operaciones de escritura:
/* Make a new session, session2, and make it causally-consistent * with session1, so that session2 will read session1's writes. */ session2 = mongoc_client_start_session (client, session_opts, &error); if (!session2) { fprintf (stderr, "couldn't start session: %s\n", error.message); goto cleanup; } /* Set the cluster time for session2 to session1's cluster time */ cluster_time = mongoc_client_session_get_cluster_time (session1); mongoc_client_session_advance_cluster_time (session2, cluster_time); /* Set the operation time for session2 to session2's operation time */ mongoc_client_session_get_operation_time (session1, ×tamp, &increment); mongoc_client_session_advance_operation_time (session2, timestamp, increment); /* Run a find on session2, which should now find all writes done * inside of session1 */ find_opts = bson_new (); res = mongoc_client_session_append (session2, find_opts, &error); if (!res) { fprintf (stderr, "couldn't add session to opts: %s\n", error.message); goto cleanup; } find_query = BCON_NEW ("end", BCON_NULL); read_prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY); cursor = mongoc_collection_find_with_opts (coll, query, find_opts, read_prefs); while (mongoc_cursor_next (cursor, &result)) { json = bson_as_relaxed_extended_json (result, NULL); fprintf (stdout, "Document: %s\n", json); bson_free (json); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "cursor failure: %s\n", error.message); goto cleanup; }
using (var session2 = client.StartSession(new ClientSessionOptions { CausalConsistency = true })) { session2.AdvanceClusterTime(session1.ClusterTime); session2.AdvanceOperationTime(session1.OperationTime); var items = client.GetDatabase( "test", new MongoDatabaseSettings { ReadPreference = ReadPreference.Secondary, ReadConcern = ReadConcern.Majority, WriteConcern = new WriteConcern(WriteConcern.WMode.Majority, TimeSpan.FromMilliseconds(1000)) }) .GetCollection<BsonDocument>("items"); var filter = Builders<BsonDocument>.Filter.Eq("end", BsonNull.Value); foreach (var item in items.Find(session2, filter).ToEnumerable()) { // process item } }
// Example 2: Advance the cluster time and the operation time to that of the other session to ensure that // this client is causally consistent with the other session and read after the two writes. ClientSession session2 = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); session2.advanceClusterTime(session1.getClusterTime()); session2.advanceOperationTime(session1.getOperationTime()); items = client.getDatabase("test") .withReadPreference(ReadPreference.secondary()) .withReadConcern(ReadConcern.MAJORITY) .withWriteConcern(WriteConcern.MAJORITY.withWTimeout(1000, TimeUnit.MILLISECONDS)) .getCollection("items"); for (Document item: items.find(session2, eq("end", BsonNull.VALUE))) { System.out.println(item); }
async with await client.start_session(causal_consistency=True) as s2: s2.advance_cluster_time(s1.cluster_time) s2.advance_operation_time(s1.operation_time) items = client.get_database( "test", read_preference=ReadPreference.SECONDARY, read_concern=ReadConcern("majority"), write_concern=WriteConcern("majority", wtimeout=1000), ).items async for item in items.find({"end": None}, session=s2): print(item)
$s2 = $client->startSession( ['causalConsistency' => true], ); $s2->advanceClusterTime($s1->getClusterTime()); $s2->advanceOperationTime($s1->getOperationTime()); $items = $client->selectDatabase( 'test', [ 'readPreference' => new \MongoDB\Driver\ReadPreference(\MongoDB\Driver\ReadPreference::SECONDARY), 'readConcern' => new \MongoDB\Driver\ReadConcern(\MongoDB\Driver\ReadConcern::MAJORITY), 'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000), ], )->items; $result = $items->find( ['end' => ['$exists' => false]], ['session' => $s2], ); foreach ($result as $item) { var_dump($item); }
with client.start_session(causal_consistency=True) as s2: s2.advance_cluster_time(s1.cluster_time) s2.advance_operation_time(s1.operation_time) items = client.get_database( "test", read_preference=ReadPreference.SECONDARY, read_concern=ReadConcern("majority"), write_concern=WriteConcern("majority", wtimeout=1000), ).items for item in items.find({"end": None}, session=s2): print(item)
let options = ClientSessionOptions(causalConsistency: true) let result2: EventLoopFuture<Void> = client2.withSession(options: options) { s2 in // The cluster and operation times are guaranteed to be non-nil since we already used s1 for operations above. s2.advanceClusterTime(to: s1.clusterTime!) s2.advanceOperationTime(to: s1.operationTime!) dbOptions.readPreference = .secondary let items2 = client2.db("test", options: dbOptions).collection("items") return items2.find(["end": .null], session: s2).flatMap { cursor in cursor.forEach { item in print(item) } } }
try client2.withSession(options: ClientSessionOptions(causalConsistency: true)) { s2 in // The cluster and operation times are guaranteed to be non-nil since we already used s1 for operations above. s2.advanceClusterTime(to: s1.clusterTime!) s2.advanceOperationTime(to: s1.operationTime!) dbOptions.readPreference = .secondary let items2 = client2.db("test", options: dbOptions).collection("items") for item in try items2.find(["end": .null], session: s2) { print(item) } }
Limitaciones
Las siguientes operaciones que construyen estructuras en memoria no son coherentes en términos de causalidad:
Operación | notas |
|---|---|
| |
Devuelve un error si la operación está asociada con una sesión de cliente causalmente coherente. | |
Devuelve un error si la operación está asociada con una sesión de cliente causalmente coherente. | |
Devuelve un error si la operación está asociada con una sesión de cliente causalmente coherente. | |
Devuelve un error si la operación está asociada con una sesión de cliente causalmente coherente. | |