Database Manual / Data Modeling / Data Consistency

Enforce Data Consistency with Transactions强制执行与事务的数据一致性

You can use transactions to enforce consistency between collections that contain duplicated data. Transactions update multiple collections in a single atomic operation.您可以使用事务来强制包含重复数据的集合之间的一致性。事务在单个原子操作中更新多个集合。

Use transactions to enforce consistency if your application must always return up-to-date data and can tolerate potential negative performance impact during periods of heavy reads.如果应用程序必须始终返回最新数据,并且可以在大量读取期间容忍潜在的负面性能影响,则使用事务来强制一致性。

Transactions might not be as performant as other methods of enforcing data consistency. Read performance might be negatively impacted while a transaction is open. However, transactions ensure that the data read by the client is always current.事务的性能可能不如其他强制数据一致性的方法。事务打开时,读取性能可能会受到负面影响。但是,事务确保客户端读取的数据始终是最新的。

About this Task关于此任务

To use transactions, you must connect to a replica set or sharded cluster. You cannot use transactions on standalone deployments.要使用事务,您必须连接到副本集或分片集群。您不能在独立部署上使用事务。

Before you Begin开始之前

Review the different methods to enforce data consistency to ensure that transactions are the best approach for your application. For more information, see Data Consistency.审查强制数据一致性的不同方法,以确保事务是应用程序的最佳方法。有关详细信息,请参阅数据一致性

Steps步骤

The following example enforces data consistency in an e-commerce application. The example schema duplicates product information in the products and sellers collections. This schema design optimizes queries for both products and sellers.以下示例强制电子商务应用程序中的数据一致性。示例模式复制了productssellers集合中的产品信息。这种模式设计优化了产品和卖家的查询。

When a product is updated, such as when its price changes, it is critical that the price is consistent in the products and sellers collections. Therefore, transactions are a reasonable method to enforce data consistency in this application.当产品更新时,例如当其价格发生变化时,productssellers集合中的价格保持一致至关重要。因此,事务是在此应用程序中强制数据一致性的合理方法。

1

Create the products collection创建产品集合

use test

db.products.insertMany(
[
{
sellerId: 456,
name: "sweater",
price: 30,
rating: 4.9
},
{
sellerId: 456,
name: "t-shirt",
price: 10,
rating: 4.2
},
{
sellerId: 456,
name: "vest",
price: 20,
rating: 4.7
}
]
)
2

Create the sellers collection创建卖家集合

use test

db.sellers.insertOne(
{
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: 20
}
]
}
)
3

Configure a transaction to handle updates配置事务以处理更新

Note

The following example uses a transaction in mongosh. To see transaction examples for MongoDB drivers, see Transactions.以下示例使用mongosh中的事务。要查看MongoDB驱动程序的事务示例,请参阅事务

The following example uses a transaction to update the price of the vest in both the products and sellers collections:以下示例使用事务来更新productssellers集合中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();

Results结果

To confirm that the price was updated and that the data is consistent, query the products and sellers collections.要确认价格已更新且数据一致,请查询productssellers集合。

Query the Products Collection查询产品集合

db.products.find( { sellerId: 456, name: "vest" } )

Output:输出:

[
{
_id: ObjectId("64d506c3ddebf45734d06c58"),
sellerId: 456,
name: 'vest',
price: 25,
rating: 4.7
}
]

Query the Sellers Collection查询卖家收款

db.sellers.find( { id: 456, "products.name": "vest" } )

Output:输出:

[
{
_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 }
]
}
]

Learn More了解更多

To see other ways to enforce data consistency, see:要查看强制数据一致性的其他方法,请参阅: