生产注意事项

要使用事务, 部署的所有成员的版本:

部署
最低限度featureCompatibilityVersion
副本集
4.0
分片集群
4.2

默认情况下,事务的运行时间必须少于一分钟。您可以使用 实例transactionLifetimeLimitSeconds来 修改此限制mongod。对于分片集群,必须为所有分片副本集成员修改该参数。超过此限制的事务将被视为已过期,并将通过定期清理过程中止。

MongoDB 根据需要创建尽可能多的 oplog 条目来封装事务中的所有写操作,而不是为事务中的所有写操作创建一个条目。这消除了单个 oplog 条目对其所有写入操作施加的事务总大小 16MB 的限制。尽管取消了总大小限制,但每个 oplog 条目仍然必须在 BSON 文档大小限制 16MB 之内。

单个Oplog在16M限制内,可使用多个oplog封装。

不能在具有writeConcernMajorityJournalDefault设置为false的碎片的分片集群上运行事务。(例如具有使用内存存储引擎的投票成员的分片)。

默认情况下,事务最多等待5几毫秒来获取事务中操作所需的锁。如果事务无法在几5毫秒内获取所需的锁,则事务将中止。

事务在中止或提交时释放所有锁。

您可以使用该maxTransactionLockRequestTimeoutMillis 参数来调整事务等待获取锁的时间。增加maxTransactionLockRequestTimeoutMillis允许事务中的操作等待指定的时间来获取所需的锁。这可以帮助避免瞬时并发锁获取时的事务中止,例如快速运行的元数据操作。但是,这可能会延迟死锁事务操作的中止。

maxTransactionLockRequestTimeoutMillis to -1  您还可以使用特定于操作的超时。

需要集合锁的DDL操作

db.collection.createIndex()DDL 操作employees

需要数据库锁的DDL操作

在正在进行的collMod事务完成之前,collMod 操作必须等待获取锁。影响hr数据库或其任何集合并在挂起期间启动的任何新事务必须等到 collMod完成后。

事务内的读取操作可能会返回旧数据,这称为 陈旧读取。事务内的读取操作不能保证看到其他已提交事务执行的写入或非事务写入。例如,考虑以下序列:

  1. 事务正在进行中。

  2. 事务外的写入会删除文档。

  3. 事务内的读取操作可以读取现在已删除的文档,因为该操作使用写入操作之前的快照。

为了避免事务内的读取返回旧数据,查找更新可以使用db.collection.findOneAndUpdate()方法。

示例

 

db.getSiblingDB("hr").employees.insertOne(
   { _id: 1, status: "Active" }
)

 

session = db.getMongo().startSession( { readPreference: { mode: "primary" } } )

 

session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } )

employeesCollection = session.getDatabase("hr").employees

 

  • 在事务内部使用db.collection.findOneAndUpdate()

employeeDoc = employeesCollection.findOneAndUpdate(
   { _id: 1, status: "Active" },
   { $set: { lockId: ObjectId() } },
   { returnNewDocument: true }
)

 

  • 提交事务

session.commitTransaction()

 

posted @ 2024-05-20 05:36  wongchaofan  阅读(3)  评论(0编辑  收藏  举报