Overview
在本指南中,您可以了解如何使用 Kotlin Sync 驱动程序执行事务。事务允许您运行一系列操作,这些操作在提交事务之前不会更改任何数据。如果事务中的任何操作返回错误,驱动程序就会取消事务,并在所有数据更改变得可见之前将其丢弃。
在MongoDB中,事务在逻辑会话中运行。 会话是您打算按顺序运行的一组相关读取或写入操作。 会话可为一群组操作启用因果一致性,并允许您在符合ACID的ACID 事务中运行操作,该ACID 事务满足原子性、一致性、隔离性性和持久性的预期。 MongoDBACID 一致性保证ACID 事务操作中涉及的数据保持一致,即使操作遇到意外错误。
使用Kotlin同步驱动程序时,您可以从 MongoClient实例创建一个新会话,并将其类型定义为 ClientSession。我们建议您将 MongoClient 重复用于多个会话和事务,而不是每次都创建一个新客户端。
警告
仅应将 ClientSession 与创建它的 MongoClient(或关联的 MongoDatabase 或 MongoCollection)一起使用。将 ClientSession 与其他 MongoClient 一起使用会导致操作错误。
因果一致性(Causal Consistency)
MongoDB在某些客户端会话中实现因果一致性。因果一致性模型ACID 一致性保证在分布式系统中,会话中的操作按因果顺序运行。客户端观察到的结果与因果关系或操作之间的依赖关系一致。示例,如果您执行一系列操作,其中一个操作在逻辑上依赖于另一个操作的结果,则任何后续读取都会反映这种依赖关系。
为了保证因果一致性,客户端端会话必须满足以下要求:
启动会话时,驱动程序必须启用因果一致性选项。该选项默认启用。
操作必须在单个线程的单个会话中运行。否则,会话或线程必须相互传达optime和集群时间值。 要查看传达这些值的两个会话的示例,请参阅MongoDB Server手册中的因果一致性示例。
您必须使用
ReadConcern.MAJORITY读关注(read concern)。您必须使用
WriteConcern.MAJORITY写关注(write concern)。这是默认的写关注(write concern)值。
下表描述了因果一致会话提供的ACID 一致性保证:
保证 | 说明 |
|---|---|
读取写入操作 | 读取操作会反映之前写入操作的结果。 |
单调读取 | 读取操作不会返回反映比先前读取操作更早的数据状态的结果。 |
单调写入 | 如果写入操作必须先于其他写入操作,则服务器会先运行此写入操作。 示例,如果调用 |
读取后写入 | 如果写入操作必须在其他读取操作之后执行,服务器会先执行读取操作。 示例,如果您调用 |
提示
要学习;了解有关本节中提到的概念的更多信息,请参阅以下MongoDB Server手册条目:
样本数据
本指南中的示例使用来自 Atlas 示例数据集的 sample_restaurants.restaurants 集合。要了解如何创建免费的 MongoDB 部署并加载示例数据集,请参阅 MongoDB入门指南。
此集合中的文档由以下Kotlin数据类建模:
data class Restaurant(val name: String, val cuisine: String)
方法
在MongoClient实例上使用startSession()方法创建ClientSession 。 然后,您可以使用ClientSession提供的方法修改会话状态。 下表描述了可用于管理ACID 事务的方法:
方法 | 说明 |
|---|---|
| 在此会话上启动使用给定选项配置的新ACID 事务。如果会话已存在正在进行的ACID 事务,则返回错误。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 startTransaction() 页面。参数: |
| 结束此会话的ACID 事务。如果该会话没有活动ACID 事务或者ACID 事务已提交或结束,则返回错误。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 abortTransaction() 页面。 |
| 提交此会话的活动事务。如果此会话没有活动事务或事务已结束,则返回错误。要了解有关此方法的更多信息,请参阅服务器手册中的 commitTransaction() 页面。 |
| 在此会话上启动ACID 事务,并在ACID 事务中运行给定函数。参数:ACID |
例子
以下示例演示了如何通过以下步骤创建会话、创建ACID 事务以及在一个ACID 事务中将文档插入到集合中:
使用
startSession()方法从客户端创建会话。定义
insertRestaurantsInTransaction()方法以将多个文档插入到restaurants集合中。使用
withTransaction()方法启动ACID 事务。withTransaction()方法运行插入操作并提交ACID 事务。 如果任何操作导致错误,withTransaction()将取消该ACID 事务。使用
MongoClient.close()方法关闭与服务器的连接。
// Creates a new MongoClient to manage your connection val client = MongoClient.create("<connection string>") // Gets the database and collection val database = client.getDatabase("sample_restaurants") val collection = database.getCollection<Restaurant>("restaurants") // Inserts restaurants into the collection fun insertRestaurantsInTransaction(session: ClientSession) { // Inserts restaurants within the transaction collection.insertOne( session, Restaurant("Kotlin Sync Pizza", "Pizza") ) collection.insertOne( session, Restaurant("Kotlin Sync Burger", "Burger") ) } // Starts a client session client.startSession().use { session -> try { // Sets transaction options val txnOptions = TransactionOptions.builder() .readConcern(ReadConcern.LOCAL) .writeConcern(WriteConcern.MAJORITY) .build() // Uses the withTransaction method to start a transaction and run the given function session.withTransaction({ insertRestaurantsInTransaction(session) println("Transaction succeeded") }, txnOptions) } catch (e: Exception) { println("Transaction failed: ${e.message}") } } // Closes the MongoClient client.close()
如果需要更好地控制事务,可以使用startTransaction()方法。 您可以将此方法与上一节中描述的commitTransaction()和abortTransaction()方法结合使用,以手动管理ACID 事务生命周期。
注意
不支持并行操作
Kotlin 同步驱动程序不支持在单个事务中运行并行操作。
如果您使用的是MongoDB Server v8.0 或更高版本,则可以使用批量写入操作在单个ACID 事务中对多个命名空间执行写入操作。要学习;了解更多信息,请参阅批量写入操作指南的客户端批量写入部分。更多信息
要了解有关本指南中提到的概念的更多信息,请参阅服务器手册中的以下页面:
要学习;了解有关ACID compliance的更多信息,请参阅什么是数据库管理系统中的ACID属性? MongoDB网站上的文章。
API 文档
要进一步了解本指南所讨论的任何类型或方法,请参阅以下 API 文档: