MongoDB-CN-Manual
搜索文档…
MongoDB事务

Transactions (Version 5.0)

事务

In MongoDB, an operation on a single document is atomic. Because you can use embedded documents and arrays to capture relationships between data in a single document structure instead of normalizing across multiple documents and collections, this single-document atomicity obviates the need for multi-document transactions for many practical use cases.
For situations that require atomicity of reads and writes to multiple documents (in a single or multiple collections), MongoDB supports multi-document transactions. With distributed transactions, transactions can be used across multiple operations, collections, databases, documents, and shards.
在MongoDB中,对单个文档的操作是原子的。由于可以在单个文档结构中使用内嵌文档和数组来获得数据之间的关系,而不必跨多个文档和集合进行范式化,所以这种单文档原子性避免了许多实际场景中对多文档事务的需求。
对于那些需要对多个文档(在单个或多个集合中)进行原子性读写的场景,MongoDB支持多文档事务。而使用分布式事务,事务可以跨多个操作、集合、数据库、文档和分片使用。

Transactions API

事务API

➤ Use the Select your language drop-down menu in the upper-right to set the language of the following example.
➤ 使用右上角的Select your language下拉菜单来设置以下示例的语言。
This example highlights the key components of the transactions API.
此示例突出显示了事务API的关键组件。
The example uses the new callback API for working with transactions, which starts a transaction, executes the specified operations, and commits (or aborts on error). The new callback API also incorporates retry logic for TransientTransactionError or UnknownTransactionCommitResult commit errors.
该示例使用新的回调API来进行事务处理,其中涉及启动事务、执行指定的操作并提交(或在出错时中止)。新的回调API还包含针对TransientTransactionErrorUnknownTransactionCommitResult提交错误的重试逻辑。
IMPORTANT
  • Recommended. Use the MongoDB driver updated for the version of your MongoDB deployment. For transactions on MongoDB 4.2 deployments (replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2.
  • When using the drivers, each operation in the transaction must be associated with the session (i.e. pass in the session to each operation).
  • In MongoDB 4.2 and earlier, you cannot create collections in transactions. Write operations that result in document inserts (e.g. insert or update operations with upsert: true) must be on existing collections if run inside transactions.
  • Starting in MongoDB 4.4, you can create collections in transactions implicitly or explicitly. You must use MongoDB drivers updated for 4.4, however. See Create Collections and Indexes In a Transaction for details.
重要
  • 推荐。使用针对MongoDB部署版本更新的MongoDB驱动程序。对于MongoDB 4.2部署(副本集和分片集群上的事务,客户端必须使用为MongoDB 4.2更新的MongoDB驱动程序。
  • 使用驱动程序时,事务中的每个操作必须与会话相关联(即将会话传递给每个操作)。
  • 事务中的操作使用事务级读关注,[事务级写关注](https ://docs.mongodb.com/manual/core/transactions/#std-label-transactions-write-concern)和事务级读偏好
  • 在MongoDB 4.2及更早版本中,你无法在事务中创建集合。如果在事务内部运行会导致文档插入的写操作(例如insert或带有upsert: true的更新操作),必须在已存在的集合上才能执行。
  • 从MongoDB 4.4开始,你可以隐式或显式地在事务中创建集合。但是,必须使用针对4.4更新的MongoDB驱动程序。有关详细信息,请参阅在事务中创建集合和索引
1
static bool
2
with_transaction_example (bson_error_t *error)
3
{
4
mongoc_client_t *client = NULL;
5
mongoc_write_concern_t *wc = NULL;
6
mongoc_read_concern_t *rc = NULL;
7
mongoc_read_prefs_t *rp = NULL;
8
mongoc_collection_t *coll = NULL;
9
bool success = false;
10
bool ret = false;
11
bson_t *doc = NULL;
12
bson_t *insert_opts = NULL;
13
mongoc_client_session_t *session = NULL;
14
mongoc_transaction_opt_t *txn_opts = NULL;
15
16
/* For a replica set, include the replica set name and a seedlist of the
17
* members in the URI string; e.g.
18
* uri_repl = "mongodb://mongodb0.example.com:27017,mongodb1.example.com:" \
19
* "27017/?replicaSet=myRepl";
20
* client = test_framework_client_new (uri_repl);
21
* For a sharded cluster, connect to the mongos instances; e.g.
22
* uri_sharded =
23
* "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/";
24
* client = test_framework_client_new (uri_sharded);
25
*/
26
27
client = get_client ();
28
29
/* Prereq: Create collections. */
30
wc = mongoc_write_concern_new ();
31
mongoc_write_concern_set_wmajority (wc, 1000);
32
insert_opts = bson_new ();
33
mongoc_write_concern_append (wc, insert_opts);
34
coll = mongoc_client_get_collection (client, "mydb1", "foo");
35
doc = BCON_NEW ("abc", BCON_INT32 (0));
36
ret = mongoc_collection_insert_one (
37
coll, doc, insert_opts, NULL /* reply */, error);
38
if (!ret) {
39
goto fail;
40
}
41
bson_destroy (doc);
42
mongoc_collection_destroy (coll);
43
coll = mongoc_client_get_collection (client, "mydb2", "bar");
44
doc = BCON_NEW ("xyz", BCON_INT32 (0));
45
ret = mongoc_collection_insert_one (
46
coll, doc, insert_opts, NULL /* reply */, error);
47
if (!ret) {
48
goto fail;
49
}
50
51
/* Step 1: Start a client session. */
52
session = mongoc_client_start_session (client, NULL /* opts */, error);
53
if (!session) {
54
goto fail;
55
}
56
57
/* Step 2: Optional. Define options to use for the transaction. */
58
txn_opts = mongoc_transaction_opts_new ();
59
rp = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
60
rc = mongoc_read_concern_new ();
61
mongoc_read_concern_set_level (rc, MONGOC_READ_CONCERN_LEVEL_LOCAL);
62
mongoc_transaction_opts_set_read_prefs (txn_opts, rp);
63
mongoc_transaction_opts_set_read_concern (txn_opts, rc);
64
mongoc_transaction_opts_set_write_concern (txn_opts, wc);
65
66
/* Step 3: Use mongoc_client_session_with_transaction to start a transaction,
67
* execute the callback, and commit (or abort on error). */
68
ret = mongoc_client_session_with_transaction (
69
session, callback, txn_opts, NULL /* ctx */, NULL /* reply */, error);
70
if (!ret) {
71
goto fail;
72
}
73
74
success = true;
75
fail:
76
bson_destroy (doc);
77
mongoc_collection_destroy (coll);
78
bson_destroy (insert_opts);
79
mongoc_read_concern_destroy (rc);
80
mongoc_read_prefs_destroy (rp);
81
mongoc_write_concern_destroy (wc);
82
mongoc_transaction_opts_destroy (txn_opts);
83
mongoc_client_session_destroy (session);
84
mongoc_client_destroy (client);
85
return success;
86
}
87
88
/* Define the callback that specifies the sequence of operations to perform
89
* inside the transactions. */
90
static bool
91
callback (mongoc_client_session_t *session,
92
void *ctx,
93
bson_t **reply,
94
bson_error_t *error)
95
{
96
mongoc_client_t *client = NULL;
97
mongoc_collection_t *coll = NULL;
98
bson_t *doc = NULL;
99
bool success = false;
100
bool ret = false;
101
102
client = mongoc_client_session_get_client (session);
103
coll = mongoc_client_get_collection (client, "mydb1", "foo");
104
doc = BCON_NEW ("abc", BCON_INT32 (1));
105
ret =
106
mongoc_collection_insert_one (coll, doc, NULL /* opts */, *reply, error);
107
if (!ret) {
108
goto fail;
109
}
110
bson_destroy (doc);
111
mongoc_collection_destroy (coll);
112
coll = mongoc_client_get_collection (client, "mydb2", "bar");
113
doc = BCON_NEW ("xyz", BCON_INT32 (999));
114
ret =
115
mongoc_collection_insert_one (coll, doc, NULL /* opts */, *reply, error);
116
if (!ret) {
117
goto fail;
118
}
119
120
success = true;
121
fail:
122
mongoc_collection_destroy (coll);
123
bson_destroy (doc);
124
return success;
125
}
Copied!
TIP
See also:
For an example in mongo shell, see mongo Shell Example.
同样请参阅:
有关mongoshell中的示例,请参阅mongoShell示例

Transactions and Atomicity

事务和原子性

NOTE
Distributed Transactions and Multi-Document Transactions
Starting in MongoDB 4.2, the two terms are synonymous. Distributed transactions refer to multi-document transactions on sharded clusters and replica sets. Multi-document transactions (whether on sharded clusters or replica sets) are also known as distributed transactions starting in MongoDB 4.2.
For situations that require atomicity of reads and writes to multiple documents (in a single or multiple collections), MongoDB supports multi-document transactions:
  • In version 4.0, MongoDB supports multi-document transactions on replica sets.
  • In version 4.2, MongoDB introduces distributed transactions, which adds support for multi-document transactions on sharded clusters and incorporates the existing support for multi-document transactions on replica sets.
    To use transactions on MongoDB 4.2 deployments (replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2.
Multi-document transactions are atomic (i.e. provide an "all-or-nothing" proposition):
  • When a transaction commits, all data changes made in the transaction are saved and visible outside the transaction. That is, a transaction will not commit some of its changes while rolling back others.
    Until a transaction commits, the data changes made in the transaction are not visible outside the transaction.
    However, when a transaction writes to multiple shards, not all outside read operations need to wait for the result of the committed transaction to be visible across the shards. For example, if a transaction is committed and write 1 is visible on shard A but write 2 is not yet visible on shard B, an outside read at read concern "local" can read the results of write 1 without seeing write 2.
  • When a transaction aborts, all data changes made in the transaction are discarded without ever becoming visible. For example, if any operation in the transaction fails, the transaction aborts and all data changes made in the transaction are discarded without ever becoming visible.
IMPORTANT
In most cases, multi-document transaction incurs a greater performance cost over single document writes, and the availability of multi-document transactions should not be a replacement for effective schema design. For many scenarios, the denormalized data model (embedded documents and arrays) will continue to be optimal for your data and use cases. That is, for many scenarios, modeling your data appropriately will minimize the need for multi-document transactions.
For additional transactions usage considerations (such as runtime limit and oplog size limit), see also Production Considerations.
TIP
See also:
说明
分布式事务和多文档事务
从MongoDB 4.2开始,这两个术语是同义词。分布式事务是指分片集群和副本集上的多文档事务。从MongoDB 4.2开始,多文档事务(无论是在分片集群上还是副本集上)也称为分布式事务。
对于多文档(在单个或多个集合中)读写上有原子性要求的场景,MongoDB提供了多文档事务支持:
  • 在4.0版本中,MongoDB支持副本集上的多文档事务。
  • 在4.2版本中,MongoDB引入了分布式事务,增加了对分片集群上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
    为了在MongoDB 4.2部署(副本集和分片集群)上使用事务,客户端必须使用为MongoDB 4.2更新的MongoDB驱动程序。
Multi-document transactions are atomic (i.e. provide an "all-or-nothing" proposition):
多文档事务是原子的(即提供“全有或全无”的语义):
  • 当事务提交时,事务中所做的所有数据更改都将保存并在事务外部可见。也就是说,事务不会在回滚其他更改时提交其某些更改。
    在事务提交之前,事务中所做的数据更改在事务之外是不可见的。
    然而,当事务写入多个分片时,并非所有外部读取操作都需要等待已提交事务的结果在分片中可见。例如,如果事务已提交并且写入操作1在分片A上可见,但写入操作2在分片B上尚不可见,则外部读关注为"local"的读操作可以读取写入操作1的结果,看不到写入操作2。
  • 当事务中止时,事务中所做的所有数据更改都将被丢弃,而不会变得可见。例如,如果事务中的任何操作失败,事务就会中止,并且事务中所做的所有数据更改都将被丢弃,而不会变得可见。
重要
在大多数情况下,多文档事务比单文档写入会产生更大的性能成本,并且多文档事务的可用性不应替代有效的模型设计。对于许多场景,反范式化数据模型(嵌入文档和数组) 依然会是最适合你的数据和用例。也就是说,对于许多场景,适当地对数据进行建模可以最大限度地减少对多文档事务的需求。
有关其他事务使用注意事项(例如runtime限制和oplog大小限制),另请参阅生产注意事项
TIP
同样请参阅:

Transactions and Operations

事务和操作

Distributed transactions can be used across multiple operations, collections, databases, documents, and, starting in MongoDB 4.2, shards.
For transactions:
  • You can specify read/write (CRUD) operations on existing collections. For a list of CRUD operations, see CRUD Operations.
  • When using feature compatibility version (fcv) "4.4" or greater, you can create collections and indexes in transactions. For details, see Create Collections and Indexes In a Transaction
  • The collections used in a transaction can be in different databases.
    NOTE
    You cannot create new collections in cross-shard write transactions. For example, if you write to an existing collection in one shard and implicitly create a collection in a different shard, MongoDB cannot perform both operations in the same transaction.
  • You cannot write to capped collections. (Starting in MongoDB 4.2)
  • You cannot read/write to collections in the config, admin, or local databases.
  • You cannot write to system.* collections.
  • You cannot return the supported operation's query plan (i.e. explain).
  • For cursors created outside of a transaction, you cannot call getMore inside the transaction.
  • For cursors created in a transaction, you cannot call getMore outside the transaction.
  • Starting in MongoDB 4.2, you cannot specify killCursors as the first operation in a transaction.
For a list of operations not supported in transactions, see Restricted Operations.
TIP
When creating or dropping a collection immediately before starting a transaction, if the collection is accessed within the transaction, issue the create or drop operation with write concern "majority" to ensure that the transaction can acquire the required locks.
TIP
See also:
分布式事务可用于跨多个操作、集合、数据库、文档以及从MongoDB 4.2开始可以跨分片。
For transactions:
对于事务:
  • 可以在现有集合上指定读/写(CRUD)操作。 有关CRUD操作的列表,请参阅CRUD操作
  • 当使用功能兼容版本(fcv)"4.4"或更高版本时,可以在事务中创建集合和索引。详情请参考在事务中创建集合和索引
  • 事务中使用的集合可以位于不同的数据库中。
    提示
    你不能在跨分片的写事务中创建新集合。例如,如果你想对一个分片中已存在的集合进行写入且在另外一个不同的分片中隐式地创建集合,那么MongoDB无法在同一事务中执行这两种操作。
  • 你不能写入capped集合。(从 MongoDB 4.2 开始)
  • 你不能读/写configadminlocal数据库中的集合。
  • 你不能写system.*集合。
  • 你不能返回这类支持操作的查询计划(即explain)。
  • 对于在事务外部创建的游标,你不能在事务内部调用getMore
  • 对于在事务内创建的游标,你不能在事务外调用getMore
  • Starting in MongoDB 4.2, you cannot specify killCursors as the first operation in a transaction.
  • 从MongoDB 4.2开始,你不能将killCursors定义为事务中的第一个操作。
有关事务中不支持的操作列表,请参阅受限操作
提示
在开始事务之前立即创建或删除集合时,如果在事务内访问该集合,注意使用写关注"majority"来执行这些创建或删除操作,从而确保事务可以获取到所需要的锁。
提示
同样请参阅:

Create Collections and Indexes In a Transaction

在事务中创建集合和索引

Starting in MongoDB 4.4 with feature compatibility version (fcv) "4.4", you can create collections and indexes inside a multi-document transaction unless the transaction is a cross-shard write transaction. With "4.2" or less, operations that affect the database catalog, such as creating or dropping a collection or an index, are disallowed in transactions.
When creating a collection inside a transaction:
When creating an index inside a transaction [1], the index to create must be on either:
  • a non-existing collection. The collection is created as part of the operation.
  • a new empty collection created earlier in the same transaction.
[1]
You can also run db.collection.createIndex() and db.collection.createIndexes() on existing indexes to check for existence. These operations return successfully without creating the index.
从MongoDB 4.4开始,使用功能兼容性版本(fcv)"4.4",可以在多文档事务中创建集合和索引,除非事务是跨分片写入事务。如果使用"4.2"或更低版本,事务中不允许使用影响数据库目录的操作,例如创建或删除集合和索引。
当在事务内部创建一个集合时:
在事务中创建索引[[1]](https: //docs.mongodb.com/manual/core/transactions/#footnote-create-existing-index),要创建的索引需满足下面两者之一情况:
  • 一个不存在的集合。集合的创建是作为操作的一部分。
  • 先前在同一事务中创建的新空集合。
[1]
还可以对现有索引运行db.collection.createIndex()db.collection.createIndexes()来检查是否存在。这些操作会成功地返回且不会创建索引。
Restrictions
限制
TIP
See also:
提示
同样请参阅:

Count Operation

To perform a count operation within a transaction, use the $count aggregation stage or the $group (with a $sum expression) aggregation stage.
MongoDB drivers compatible with the 4.0 features provide a collection-level API countDocuments(filter, options) as a helper method that uses the $group with a $sum expression to perform a count. The 4.0 drivers have deprecated the count() API.
Starting in MongoDB 4.0.3, the mongo shell provides the db.collection.countDocuments() helper method that uses the $group with a $sum expression to perform a count.

计数操作

要在事务中执行计数操作,请使用$count聚合阶段或带有[$sum](https ://docs.mongodb.com/manual/reference/operator/aggregation/sum/#mongodb-group-grp.-sum)表达式的$group聚合阶段。
与4.0特性兼容的MongoDB驱动程序提供了一个集合级别的APIcountDocuments(filter, options)作为带有$sum表达式的[$group](https://docs.mongodb.com/manual/reference/operator /aggregation/group/#mongodb-pipeline-pipe.-group)的帮助函数来执行计数。4.0驱动程序已弃用count() API。
从MongoDB4.0.3开始,mongoshell提供了在db.collection.countDocuments()中使用带有[$sum](https://docs.mongodb.com/ manual/reference/operator/aggregation/sum/#mongodb-group-grp.-sum)表达式的$group来执行计数的帮助函数。

Distinct Operation

To perform a distinct operation within a transaction:
  • For unsharded collections, you can use the db.collection.distinct() method/the distinct command as well as the aggregation pipeline with the $group stage.
  • For sharded collections, you cannot use the db.collection.distinct() method or the distinct command.
    To find the distinct values for a sharded collection, use the aggregation pipeline with the $group stage instead. For example:
    • Instead of db.coll.distinct("x"), use
      1
      db.coll.aggregate([
      2
      { $group: { _id: null, distinctValues: { $addToSet: "$x" } } },
      3
      { $project: { _id: 0 } }
      4
      ])
      Copied!
    • Instead of db.coll.distinct("x", { status: "A" }), use:
      1
      db.coll.aggregate([
      2
      { $match: { status: "A" } },
      3
      { $group: { _id: null, distinctValues: { $addToSet: "$x" } } },
      4
      { $project: { _id: 0 } }
      5
      ])
      Copied!
    The pipeline returns a cursor to a document:
    1
    { "distinctValues" : [ 2, 3, 1 ] }
    Copied!
    Iterate the cursor to access the results document.

Distinct操作

为了在事务中执行一个distinct操作:
  • 对于未分片的集合,可以使用[db.collection.distinct()](https://docs.mongodb.com/manual/reference/method/db.collection.distinct/#mongodb-method-db.collection .distinct)方法/distinct命令以及带有$group阶段的聚合管道。
  • 对于分片的集合,不能使用db.collection.distinct() 方法或者distinct命令。
    要查找分片集合的不同值,请使用带$group阶段的聚合管道作为替代。例如:
    • 替代db.coll.distinct("x"),请使用:
      1
      db.coll.aggregate([
      2
      { $group: { _id: null, distinctValues: { $addToSet: "$x" } } },
      3
      { $project: { _id: 0 } }
      4
      ])
      Copied!
    • 替代db.coll.distinct("x", { status: "A" }),请使用:
      1
      db.coll.aggregate([
      2
      { $match: { status: "A" } },
      3
      { $group: { _id: null, distinctValues: { $addToSet: "$x" } } },
      4
      { $project: { _id: 0 } }
      5
      ])
      Copied!
    管道将游标返回到文档:
    1
    { "distinctValues" : [ 2, 3, 1 ] }
    Copied!
    迭代游标来访问结果集文档。

Informational Operations

Informational commands, such as hello, buildInfo, connectionStatus (and their helper methods) are allowed in transactions; however, they cannot be the first operation in the transaction.

信息类操作

信息类操作命令,比如hello, buildInfo, connectionStatus(以及它们的辅助函数)是被允许在事务中使用的。然而,它们不能作为事务中的第一个操作。

Restricted Operations

Changed in version 4.4.
The following operations are not allowed in transactions:
TIP
See also:

受限制的操作

在4.4版本中变更。
下列这些操作在事务中是不被允许的:
提示
同样请参阅:

Transactions and Sessions

  • Transactions are associated with a session; i.e. you start a transaction for a session.
  • At any given time, you can have at most one open transaction for a session.
  • When using the drivers, each operation in the transaction must be associated with the session. Refer to your driver specific documentation for details.
  • If a session ends and it has an open transaction, the transaction aborts.

事务和会话

  • 事务是与某个会话相关联的;即你为一个会话启动一个事务。
  • 在任何给定时间,一个会话最多可以有一个打开的事务。
  • 使用驱动程序时,事务中的每个操作都必须与会话相关联。有关详细信息,请参阅你使用的驱动程序文档。
  • 如果一个会话结束了并且它有一个打开的事务,则事务会中止。

Read Concern/Write Concern/Read Preference

读关注/写关注/读偏好

Transactions and Read Preference

Operations in a transaction use the transaction-level read preference.
Using the drivers, you can set the transaction-level read preference at the transaction start:
  • If the transaction-level read preference is unset, the transaction uses the session-level read preference.
  • If transaction-level and the session-level read preference are unset, the transaction uses the client-level read preference. By default, the client-level read preference is primary.
Multi-document transactions that contain read operations must use read preference primary. All operations in a given transaction must route to the same member.

事务和读偏好

在事务中使用事务级读偏好的操作。
在使用驱动时,你可以在事务开始时设置事务级别的读偏好
  • 如果事务级别的读偏好没有设置,事务会使用会话级别的读偏好。
  • 如果事务级别和会话级别的读偏好没有设置,事务使用客户端级别的读偏好。默认情况下,客户端级别的读偏好是primary
包含读操作的多文档事务必须使用primary读偏好。在一个给定事务中的所有操作都必须路由到同一个成员。

Transactions and Read Concern

Operations in a transaction use the transaction-level read concern. That is, any read concern set at the collection and database level is ignored inside the transaction.
You can set the transaction-level read concern at the transaction start.
  • If the transaction-level read concern is unset, the transaction-level read concern defaults to the session-level read concern.
  • If transaction-level and the session-level read concern are unset, the transaction-level read concern defaults to the client-level read concern. By default, client-level read concern is "local" for reads against the primary. See also:
Transactions support the following read concern levels:
"local"
  • Read concern "local" returns the most recent data available from the node but can be rolled back.
  • For transactions on sharded cluster, "local" read concern cannot guarantee that the data is from the same snapshot view across the shards. If snapshot isolation is required, use "snapshot" read concern.
  • Starting in MongoDB 4.4, with feature compatibility version (fcv) "4.4" or greater, you can create collections and indexes inside a transaction. If explicitly creating a collection or an index, the transaction must use read concern "local". Implicit creation of a collection can use any of the read concerns available for transactions.
"majority"
  • Read concern "majority" returns data that has been acknowledged by a majority of the replica set members (i.e. data cannot be rolled back) if the transaction commits with write concern "majority".
  • If the transaction does not use write concern "majority" for the commit, the "majority" read concern provides no guarantees that read operations read majority-committed data.
  • For transactions on sharded cluster, "majority" read concern cannot guarantee that the data is from the same snapshot view across the shards. If snapshot isolation is required, use "snapshot" read concern.
"snapshot"
  • Read concern "snapshot" returns data from a snapshot of majority committed data if the transaction commits with write concern "majority".
  • If the transaction does not use write concern "majority" for the commit, the "snapshot" read concern provides no guarantee that read operations used a snapshot of majority-committed data.
  • For transactions on sharded clusters, the "snapshot" view of the data is synchronized across shards.

事务和读关注

在事务中的操作会使用事务级读关注。也就是说,在事务内部忽略在集合和数据库级别设置的任何读关注。
可以在事务开始时设置事务级别的读关注
  • 如果事务级别的读关注没有设置,事务级的读关注默认为会话级的读关注。
  • 如果事务级和会话级的读关注没有设置,事务级的读关注默认为客户端级的读关注。默认情况下,客户端级的读取关注是"local"用于针对主节点的读取。同样请参阅:
事务支持下列的读关注级别:
"local"
  • 读关注"local"会返回节点最新可用的数据,但可能被回滚。
  • 对于分片集群上的事务,"local"读关注不能保证数据来自同一个跨分片的快照视图。如果需要快照隔离,请使用 "snapshot"读关注。
  • 从MongoDB 4.4开始,使用功能兼容版本(fcv)"4.4"或更高,可以在事务内创建集合和索引。如果显式地创建集合或索引,事务必须使用读关注"local"隐式地创建集合可使用任何适用于事务的读关注。
"majority"
  • 如果事务以写关注“majority”的方式提交,则读关注"majority"会返回已被副本集中大多数成员确认的数据(即数据不会被回滚)。
  • 如果事务不用写关注“majority”的方式提交,"majority"读关注不能保证读操作读取到大多数已提交的数据。
  • 对于分片集群上的事务,"majority"读关注不能保证数据来自同一个跨分片的快照视图。如果需要快照隔离,请使用"snapshot"读关注。
"snapshot"

Transactions and Write Concern

Transactions use the transaction-level write concern to commit the write operations. Write operations inside transactions must be issued without explicit write concern specification and use the default write concern. At commit time, the writes are then commited using the transaction-level write concern.
TIP
Do not explicitly set the write concern for the individual write operations inside a transaction. Setting write concerns for the individual write operations inside a transaction results in an error.
You can set the transaction-level write concern at the transaction start:
  • If the transaction-level write concern is unset, the transaction-level write concern defaults to the session-level write concern for the commit.
  • If the transaction-level write concern and the session-level write concern are unset, transaction-level write concern defaults to the client-level write concern. By default, client-level write concern is w: 1. See also Default MongoDB Read Concerns/Write Concerns.
Transactions support all write concern w values, including:
w: 1
  • Write concern w: 1 returns acknowledgement after the commit has been applied to the primary.
    IMPORTANT
    When you commit with w: 1, your transaction can be rolled back if there is a failover.
  • When you commit with w: 1 write concern, transaction-level "majority" read concern provides no guarantees that read operations in the transaction read majority-committed data.
  • When you commit with w: 1 write concern, transaction-level "snapshot" read concern provides no guarantee that read operations in the transaction used a snapshot of majority-committed data.
w: "majority"
  • Write concern w: "majority" returns acknowledgement after the commit has been applied to a majority (M) of voting members; i.e. the commit has been applied to the primary and (M-1) voting secondaries.
  • When you commit with w: "majority" write concern, transaction-level "majority" read concern guarantees that operations have read majority-committed data. For transactions on sharded clusters, this view of the majority-committed data is not synchronized across shards.
  • When you commit with w: "majority" write concern, transaction-level "snapshot" read concern guarantees that operations have from a synchronized snapshot of majority-committed data.
NOTE
Regardless of the write concern specified for the transaction, the commit operation for a sharded cluster transaction includes some parts that use {w: "majority", j: true} write concern.

事务和写关注

事务使用事务级写关注来提交写操作。事务内的写操作必须没有显式定义写关注,并使用默认的写关注。在提交时,然后使用事务级写关注提交写入。
提示
不要为事务内的单个写操作显式设置写关注。为事务内的单个写操作设置写关注会导致错误。
可以在事务开始时设置事务级别的写关注
  • 如果事务级别的写关注没有设置,事务级写关注默认为提交的会话级写关注。
  • 如果事务级写关注和会话级写关注没有设置,事务级写关注默认为客户端级写关注。默认情况下,客户端写关注为w: 1。也可以参考默认MongoDB读关注/写关注
事务支持所有写关注w的值,包括:
w: 1
  • 写关注w: 1会在提交已经被应用到主节点后反馈确认结果。
    重要
    当使用w: 1提交,事务在发生故障时可能会回滚。
  • 当使用w: 1写关注提交,事务级"majority"的读关注无法保证事务中的读操作能读取大多数已提交的数据。
  • 当使用 w: 1写关注提交,事务级"snapshot"的读关注无法保证事务中的读操作能使用大多数已提交数据的快照。
w: "majority"
  • 写关注w: "majority"会在提交的数据被应用到大多数(M)有投票权的成员后返回确认;即提交数据已被应用到主节点和(M-1)有投票权的从节点。
  • 当使用w: "majority"写关注提交时,事务级w: "majority"读关注可以确保操作能读取到大多数已提交的数据。对于分片集群上的事务,这种大多数已提交数据的视图在分片之间不会同步。
  • 当使用w: "majority"写关注提交时,事务级"snapshot"读关注可以确保证操作能获取来自大多数已提交数据的同步快照。
说明
不管为事务指定的写关注,分片集群事务的提交操作包括一部分使用了{w: "majority", j: true}写关注的操作。

General Information

通用信息

Production Considerations

生产注意事项

For various production considerations with using transactions, see Production Considerations. In addition, or sharded clusters, see also Production Considerations (Sharded Clusters).
关于使用事务的各种生产注意事项,请参阅生产注意事项。另外,如果是分片集群,同样请参阅生产注意事项(分片集群)

Arbiters

仲裁节点

Transactions whose write operations span multiple shards will error and abort if any transaction operation reads from or writes to a shard that contains an arbiter.
See also Disabled Read Concern Majority for transaction restrictions on shards that have disabled read concern majority.
如果任何事务操作从包含仲裁节点的分片读取或写入,其写操作跨越多个分片的事务将出错并中止。
另请参阅Disabled Read Concern Majority,了解在分片上已禁用读关注 majority的事务限制。

Disabled Read Concern Majority

禁用读关注majority

A 3-member PSA (Primary-Secondary-Arbiter) replica set or a sharded cluster with 3-member PSA shards may have disabled read concern majority (--enableMajorityReadConcern false or replication.enableMajorityReadConcern: false)
  • On sharded clusters,
    If a transaction involves a shard that has disabled read concern "majority", you cannot use read concern "snapshot" for the transaction. You can only use read concern "local" or "majority" for the transaction. If you use read concern "snapshot", the transaction errors and aborts.readConcern level 'snapshot' is not supported in sharded clusters when enableMajorityReadConcern=false.Transactions whose write operations span multiple shards will error and abort if any of the transaction's read or write operations involves a shard that has disabled read concern "majority".
  • On replica set,
    You can specify read concern "local" or "majority" or "snapshot" even in the replica set has disabled read concern "majority".However, if you are planning to transition to a sharded cluster with disabled read concern majority shards, you may wish to avoid using read concern "snapshot".
TIP
To check if read concern "majority" is disabled, You can run db.serverStatus() on the mongod instances and check the storageEngine.supportsCommittedReads field. If false, read concern "majority" is disabled.
三成员PSA(主-从-仲裁)副本集或者拥有三成员PSA分片的分片集群可能已经禁用了读关注majority(--enableMajorityReadConcern falsereplication.enableMajorityReadConcern: false
  • 在分片集群上,
    如果事务涉及到具有禁用读关注“majority”的分片,则不能对事务使用读关注"snapshot"。你只能对事务使用读关注"local"或者"majority"。如果使用读关注"snapshot",则事务会报错并中止。readConcern level 'snapshot' is not supported in sharded clusters when enableMajorityReadConcern=false。如果事务的任何读取或写入操作涉及已禁用读关注"majority"的分片,则其跨越多个分片进行写入操作的事务会出错并中止。
  • 在副本集上,
    可以定义读关注"local""majority"或者甚至在已禁用读关注"majority"的副本集上使用"snapshot"。但是,如果你计划迁移到有分片禁用读关注majority的分片集群上,可能希望避免使用读关注"snapshot"
提示
要检查读关注"majority"是否被禁用,可以在mongod实例上运行db.serverStatus()并检查storageEngine.supportsCommittedReads字段。如果值为false,则表示读关注"majority"已禁用。
更多信息请参考三成员PSA架构三成员PSA分片

Shard Configuration Restriction

分片配置限制

You cannot run transactions on a sharded cluster that has a shard with writeConcernMajorityJournalDefault set to false (such as a shard with a voting member that uses the in-memory storage engine).
NOTE
Regardless of the write concern specified for the transaction, the commit operation for a sharded cluster transaction includes some parts that use {w: "majority", j: true} write concern.
不能在包含writeConcernMajorityJournalDefault设置为false 分片的分片集群上运行事务(例如包含使用了内存存储引擎作为投票成员的分片)。
说明
不管为事务指定的写关注,分片集群事务的提交操作都会包含一部分使用了{w: "majority", j: true}写关注的操作。

Diagnostics

诊断

MongoDB provides various transactions metrics:
Source
Returns
Returns transactions metrics.
$currentOp aggregation pipeline
Returns:$currentOp.transaction if an operation is part of a transaction.Information on inactive sessions that are holding locks as part of a transaction.$currentOp.twoPhaseCommitCoordinator metrics for sharded transactions that involes writes to multiple shards.
db.currentOp() methodcurrentOp command
Returns:currentOp.transaction if an operation is part of a transaction.currentOp.twoPhaseCommitCoordinator metrics for sharded transactions that involes writes to multiple shards.
mongod and mongos log messages
Includes information on slow transactions (i.e. transactions that exceed the operationProfiling.slowOpThresholdMs threshhold) under the TXN log component.
MongoDB提供了多种事务相关指标:
Source
Returns
db.serverStatus()方法中的serverStatus命令
返回transactions 相关指标。
$currentOp聚合管道
如果操作作为事务的一部分则返回:$currentOp.transaction。持有锁的非活动会话的信息会作为事务的一部分。$currentOp.twoPhaseCommitCoordinator 是写入多个分片的分片事务的指标。
db.currentOp()方法中的currentOp命令
如果操作作为事务的一部分则返回currentOp.transaction$currentOp.twoPhaseCommitCoordinator是写入多个分片的分片事务的指标。
mongodmongos日志信息
TXN日志组件下包含慢事务的信息(即事务超过了operationProfiling.slowOpThresholdMs 阈值)

Feature Compatibility Version (FCV)

功能兼容版本(FCV)

To use transactions, the featureCompatibilityVersion for all members of the deployment must be at least:
Deployment
Minimum featureCompatibilityVersion
Replica Set
4.0
Sharded Cluster
4.2
To check the fCV for a member, connect to the member and run the following command:
1
db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
Copied!
For more information, see the setFeatureCompatibilityVersion reference page.
为了使用事务,部署架构中所有成员的featureCompatibilityVersion至少为:
部署架构
最小featureCompatibilityVersion
副本集
4.0
分片集群
4.2
为了检查成员的FCV,连接到成员并运行下面的命令:
1
db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
Copied!
更多信息详见setFeatureCompatibilityVersion参考页。

Storage Engines

存储引擎

Starting in MongoDB 4.2, multi-document transactions are supported on replica sets and sharded clusters where:
  • the primary uses the WiredTiger storage engine, and
  • the secondary members use either the WiredTiger storage engine or the in-memory storage engines.
In MongoDB 4.0, only replica sets using the WiredTiger storage engine supported transactions.
NOTE
You cannot run transactions on a sharded cluster that has a shard with writeConcernMajorityJournalDefault set to false, such as a shard with a voting member that uses the in-memory storage engine.
从MongoDB 4.2开始,多文档事务支持副本集和分片集群,其中:
  • 主节点使用WiredTiger存储引擎,同时
  • 从节点使用WiredTiger存储引擎或in-memory存储引擎。
在MongoDB 4.0中,只有使用WiredTiger存储引擎的副本集支持事务。
说明
你不能在包含writeConcernMajorityJournalDefault设置为 false 分片的分片集群上运行事务,例如包含使用了内存存储引擎作为投票成员的分片。

Additional Transactions Topics

附加事务主题

原文链接:https://docs.mongodb.com/manual/core/transactions/
译者:李正洋
最近更新 14d ago