必须用mongocxx::client_session启动事务且所有操作显式传入该session;事务非全局开关,需通过client创建session并绑定,crud操作须带session参数,否则绕过事务;推荐用client.with_transaction自动处理瞬态错误。

必须用 mongocxx::client_session 启动事务,且所有操作必须显式传入该 session;直接在 collection 上调用 insert_one 或 update_one 不会进入事务上下文。
事务必须绑定到 client_session 实例
事务不是全局开关,也不是 client 或 database 级别的设置。MongoDB C++ 驱动要求你先从 mongocxx::client 创建一个 mongocxx::client_session,再用它开启事务。这个 session 是事务的载体,也是因果一致性和错误回滚的边界。
-
mongocxx::client_session必须由创建它的mongocxx::client实例生成,混用会导致未定义行为或连接中断 - 每个
mongocxx::client实例不是线程安全的,其派生的client_session也必须由同一线程独占使用 - session 生命周期 ≠ 事务生命周期:调用
session.start_transaction()才真正开启事务,session.commit_transaction()或session.abort_transaction()才结束
事务内操作必须显式传入 session 参数
所有 CRUD 操作(如 insert_one、find_one_and_update、delete_many)在事务中执行时,必须把 mongocxx::client_session& 作为最后一个参数传入。漏掉这一步,操作会绕过事务,直接写入数据库。
- 错误写法:
collection.insert_one(doc.view())→ 脱离事务,立即生效 - 正确写法:
collection.insert_one(doc.view(), session)→ 受事务控制 - 读操作同样需要传 session:
collection.find(filter.view(), session),否则读取的是最新已提交快照,可能看到事务外的中间状态 - 事务内不支持隐式集合创建(MongoDB insert_one 会抛出
mongocxx::exception
推荐使用回调 API 处理 transient 错误
MongoDB 服务端可能返回 TransientTransactionError(例如临时主节点切换、网络抖动),驱动本身不自动重试。你需要手动捕获并重试整个事务逻辑,或使用封装好的回调模式 —— 这是官方文档明确推荐的方式。
- 回调函数需接收
mongocxx::client_session&并返回布尔值表示成功 - 驱动提供
mongocxx::client::with_transaction方法(注意:不是client_session的成员),它会自动处理TransientTransactionError和UnknownTransactionCommitResult的重试 - 示例签名:
client.with_transaction(callback, txn_opts),其中txn_opts可设read_concern、write_concern等 - 注意:该 API 在 mongocxx v3.7+ 才稳定支持,旧版本需自行实现重试循环
连接与 session 配置容易被忽略的细节
事务依赖底层连接稳定性与语义一致性,URI 和 client options 中几个选项直接影响事务是否可用或是否报错。
- 副本集部署必须在 URI 中指定
replicaSet=xxx,否则start_transaction()会失败并抛出logic_error - 分片集群必须连接 mongos,不能直连 shard,否则事务无法跨分片协调
- 强烈建议在
mongocxx::options::client中启用server_api_opts,指定version::k_version_1,避免 MongoDB Server 升级导致事务行为变更 - 不要在事务中使用
coll.drop()或db.create_collection()(除非 MongoDB ≥ 4.4 且驱动版本匹配),这类管理命令不被事务包裹
事务不是“加个 session 就能用”的开关,它是 session + 显式参数 + 正确连接拓扑 + 错误处理策略的组合体。最容易出问题的地方是忘记给每个操作传 session,或者在非副本集/非分片环境里强行开启事务 —— 这两种情况都不会报编译错误,但运行时会静默失败或抛出难以定位的异常。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











