文档菜单
文档首页
/ / /
C驱动程序
/

事务

在本页中

  • 概述
  • 事务API
  • 便捷API
  • 核心API
  • 事务示例
  • 附加信息
  • API文档

在本指南中,您可以学习如何使用C驱动程序执行事务。事务允许您执行一系列只有在整个事务提交后才会更改数据的操作。如果事务中的任何操作不成功,库将停止事务并丢弃所有更改的数据,这些更改在此之前永远不会可见。此功能称为原子性

在MongoDB中,事务在逻辑会话中运行。会话是一组相关读或写操作,您打算依次运行。会话使一组操作能够实现因果一致性,并允许您在符合ACID的事务中运行操作,这是指满足原子性、一致性、隔离性和持久性的预期。MongoDB保证参与事务操作的数据保持一致,即使在操作遇到意外错误时也是如此。

使用C驱动程序时,您可以从mongoc_client_t实例创建一个新的会话。然后,您可以使用生成的mongoc_client_session_t实例执行事务。

警告

仅使用与创建它的mongoc_client_t(或相关的mongoc_database_tmongoc_collection_t)一起使用的mongoc_client_session_t。使用不同mongoc_client_tmongoc_client_session_t会导致操作错误。

在本节中,您可以了解C驱动程序提供的事务API。在开始事务之前,您必须使用 mongoc_client_start_session() 函数在您的 mongoc_client_t 实例上创建一个 mongoc_client_session_t。然后,您可以使用以下任一API来执行事务

  • 便捷API

  • 核心API

C驱动程序提供了一种名为 便捷事务API 的API来管理事务生命周期。通过使用 mongoc_client_session_with_transaction() 函数在事务中运行自定义回调来实现此API。该 mongoc_client_session_with_transaction() 函数执行以下任务

  • 启动事务

  • 通过结束事务或重试来处理错误,例如当操作结果为 TransientTransactionError

  • 提交事务

本指南的 事务示例 部分演示了如何使用此API执行事务。

或者,您可以通过使用以下函数与您的 mongoc_client_session_t 实例来对您的交易生命周期有更多控制。

函数
描述
mongoc_client_session_start_transaction()
在此会话上启动一个新的交易,配置为给定的选项。如果存在无效参数,例如会话中已存在一个正在进行的交易,则返回 false 并设置提供的错误。有关此函数的更多信息,请参阅服务器手册中的 startTransaction() 页面
mongoc_client_session_abort_transaction()
结束此会话的活跃事务。如果会话没有活跃事务或事务已被提交或结束,则返回 false 并设置提供的错误。有关此函数的更多信息,请参阅服务器手册中的 abortTransaction() 页面
mongoc_client_session_commit_transaction()
提交此会话的活跃事务。如果会话没有活跃事务或事务已被结束,则返回错误。有关此函数的更多信息,请参阅服务器手册中的 commitTransaction() 页面
mongoc_client_session_destroy()
中止任何进行中的事务并结束此会话。释放与此会话相关联的所有客户端资源。

有关获取 mongoc_client_session_t 属性和修改可变会话属性的函数的更多信息,请参阅 API 文档

此示例定义了一个回调函数,用于修改 sample_bank 数据库中用于银行交易的集合中的数据。代码执行以下操作:

  1. 定义回调函数,该函数接收 mongoc_client_session_t 实例作为参数。

  2. 创建 mongoc_collection_t 实例以访问目标集合。

  3. 指定要转账的账户编号和金额。

  4. 更新客户的余额以反映转账。

  5. 记录带有时间戳的交易收据。

  6. 如果事务提交成功,则打印一条消息。

bool
transaction_callback (mongoc_client_session_t *session, void *ctx, bson_t **reply,
bson_error_t *error)
{
BSON_UNUSED(ctx);
BSON_UNUSED(reply);
mongoc_client_t *client = mongoc_client_session_get_client (session);
mongoc_collection_t *checking = mongoc_client_get_collection (client, "sample_bank", "checking");
mongoc_collection_t *savings = mongoc_client_get_collection (client, "sample_bank", "savings");
mongoc_collection_t *receipts = mongoc_client_get_collection (client, "sample_bank", "receipts");
const char *account_id = "123456";
int transfer_amount = 1000;
bson_t *filter = BCON_NEW ("account_id", BCON_UTF8 (account_id));
bson_t *update_decrement = BCON_NEW ("$inc", "{", "balance", BCON_INT32 (-transfer_amount), "}");
bson_t *update_increment = BCON_NEW ("$inc", "{", "balance", BCON_INT32 (transfer_amount), "}");
if (!mongoc_collection_update_one (checking, filter, update_decrement, NULL, NULL, &error)) {
fprintf (stderr, "Failed to update checking account: %s\n", error.message);
return false;
}
if (!mongoc_collection_update_one (savings, filter, update_increment, NULL, NULL, &error)) {
fprintf (stderr, "Failed to update savings account: %s\n", error.message);
return false;
}
bson_t *receipt = BCON_NEW ("account_id", BCON_UTF8 (account_id),
"amount", BCON_INT32 (transfer_amount),
"timestamp", BCON_DATE_TIME (bson_get_monotonic_time ()));
if (!mongoc_collection_insert_one (receipts, receipt, NULL, NULL, &error)) {
fprintf (stderr, "Failed to insert receipt: %s\n", error.message);
return false;
}
mongoc_collection_destroy (checking);
mongoc_collection_destroy (savings);
mongoc_collection_destroy (receipts);
bson_destroy (filter);
bson_destroy (update_decrement);
bson_destroy (update_increment);
bson_destroy (receipt);
printf ("Transaction successful!");
return true;
}

然后,运行以下代码以执行事务。此代码完成以下操作:

  1. 通过使用 mongoc_client_start_session() 函数从客户端创建一个会话。

  2. 调用 mongoc_client_session_with_transaction() 函数来管理事务,并将会话和回调作为参数传递。

mongoc_client_session_t *session = mongoc_client_start_session (client, NULL, NULL);
if (!session) {
fprintf (stderr, "Failed to start session\n");
mongoc_client_destroy (client);
return EXIT_FAILURE;
}
bool result =
mongoc_client_session_with_transaction (session,
(mongoc_client_session_with_transaction_cb_t) transaction_callback,
NULL, NULL, NULL, &error);
if (!result) {
fprintf (stderr, "Transaction error: %s\n", error.message);
}
mongoc_client_session_destroy (session);
mongoc_client_destroy (client);
mongoc_cleanup ();
Transaction successful!

有关本指南中提到的概念,请参阅 MongoDB 服务器手册中的以下页面

有关 ACID 兼容性的更多信息,请参阅 MongoDB 网站上的 数据库管理系统中的 ACID 属性是什么? 文章。

有关本指南中讨论的任何类型或函数的更多信息,请参阅以下 API 文档

返回

批量写入操作