使用事务强制数据一致性
您可以使用事务来强制包含重复数据的集合之间的一致性。事务在单个原子操作中更新多个集合。
如果您的应用程序必须始终返回最新的数据,并且可以容忍在大量读取期间的潜在性能下降,请使用事务来强制一致性。
事务可能不如其他强制数据一致性的方法性能高。在事务打开时,读取性能可能会受到影响。然而,事务确保客户端读取的数据始终是最新的。
关于此任务
要使用事务,您必须连接到副本集或分片集群。您不能在独立部署上使用事务。
开始之前
审查不同的强制数据一致性的方法,以确保事务是您应用程序的最佳方法。有关更多信息,请参阅数据一致性。
步骤
以下示例在电子商务应用程序中强制数据一致性。该示例模式在products
和 sellers
集合中重复产品信息。这种模式设计优化了产品和销售者的查询。
当产品更新时,例如当其价格发生变化时,确保在 products
和 sellers
集合中价格一致是至关重要的。因此,事务是强制在此应用程序中强制数据一致性的合理方法。
1
2
3
配置一个事务以处理更新
以下示例使用事务来更新vest
在products
和sellers
集合中的价格
// 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 } ] } ]
了解更多
要了解其他强制数据一致性的方法,请参阅