强制执行事务的数据一致性
您可以使用事务来实施包含重复数据的集合之间的一致性。 事务在单个原子操作中更新多个集合。
如果应用程序必须始终返回最新数据,并且在大量读取期间可以容忍潜在的负面性能影响,请使用事务来实施一致性。
事务的性能可能不如其他强制执行数据一致性的方法。当事务处于打开状态时,读取性能可能会受到负面影响。但是,事务可确保客户端读取的数据始终是最新的。
关于此任务
要使用事务,必须连接到副本集或分片集群。您不能在独立部署上使用事务。
开始之前
查看强制数据一致性的不同方法,确保事务是适用于应用程序的最佳方法。有关更多信息,请参阅数据一致性。
步骤
以下示例在电商应用程序中实施数据一致性。示例模式复制了 products
和sellers
collection中的产品信息。这种模式设计优化了产品和卖家的查询。
当产品更新时,例如当其价格发生变化时,价格在 products
和 sellers
集合中保持一致至关重要。因此,事务是在此应用程序中强制执行数据一致性的合理方法。
1
2
3
配置事务来处理更新
以下示例展示了如何使用事务更新 products
和 sellers
集合中 vest
的价格:
// Start a session session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); productsCollection = session.getDatabase("test").products; sellersCollection = session.getDatabase("test").sellers; // Start a transaction session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } ); // Operations inside the transaction try { productsCollection.updateOne( { sellerId: 456, name: "vest" }, { $set: { price: 25 } } ); sellersCollection.updateOne( { }, { $set: { "products.$[element].price": 25 } }, { arrayFilters: [ { "element.name": "vest" } ] } ); } catch (error) { // Cancel transaction on error session.abortTransaction(); throw error; } // Commit the transaction using write concern set at transaction start session.commitTransaction(); session.endSession();
结果
若要确认价格已更新且数据一致,请查询 products
和 sellers
集合。
查询产品集合
db.products.find( { sellerId: 456, name: "vest" } )
输出:
[ { _id: ObjectId("64d506c3ddebf45734d06c58"), sellerId: 456, name: 'vest', price: 25, rating: 4.7 } ]
查询卖家集合
db.sellers.find( { id: 456, "products.name": "vest" } )
输出:
[ { _id: ObjectId("64d516d9ddebf45734d06c5a"), id: 456, name: 'Cool Clothes Co', location: { address: '21643 Andreane Shores', state: 'Ohio', country: 'United States' }, phone: '567-555-0105', products: [ { name: 'sweater', price: 30 }, { name: 't-shirt', price: 10 }, { name: 'vest', price: 25 } ] } ]
了解详情
如要了解实施数据一致性的其他方法,请参阅: