mongodb事务仅支持副本集或分片集群,单节点不支持;需显式传入session参数,超时60秒不可配置;writeconcern和readconcern需合理设置以保障一致性。

事务只在副本集或分片集群上可用
单节点 MongoDB 实例不支持事务,调用 start_transaction() 会直接报错 OperationFailure: Transactions are not supported on this deployment。这是最常卡住新手的第一步。
- 本地开发时,别用
mongod --dbpath启动单机版,改用mongod --replSet rs0并执行rs.initiate() - Docker 中快速起副本集:用官方镜像的
docker-compose.yml示例,确保包含replication.replSetName配置 - 云服务(如 MongoDB Atlas)默认开副本集,但免费共享层(M0)仍不支持事务——得升到 M10 或更高
session 必须显式传入每个操作
MongoDB Python 驱动不会自动把操作绑定到当前事务上下文,漏传 session 参数等于白开事务:所有写操作会立即提交,回滚完全失效。
- 每次调用
insert_one()、update_one()、delete_many()等方法时,必须加session=session - 聚合管道中用
$out或$merge写入数据时,同样要传session;否则写入脱离事务控制 - 读操作默认不参与事务隔离,如需读已写未提交数据,得设
read_concern=ReadConcern("local"),但通常没必要
with client.start_session() as session:
with session.start_transaction():
collection_a.insert_one({"x": 1}, session=session) # ✅ 正确
collection_b.update_one({"y": 2}, {"$set": {"z": 3}}, session=session) # ✅ 正确
collection_a.insert_one({"x": 2}) # ❌ 没传 session,立刻提交,事务无法回滚它
事务有 60 秒超时且不可配置
从 start_transaction() 开始计时,超时后服务端自动中止事务并释放锁。不是客户端异常,所以 try/except 捕获不到;表现常是后续操作卡住或报 InvalidSession。
- 避免在事务里做 HTTP 请求、文件读写、长循环等阻塞操作
- 批量操作尽量用
insert_many()、bulk_write()替代多次单条调用,减少网络往返和时间消耗 - 如果真需要长流程,拆成多个短事务,用业务逻辑保证最终一致性,而不是强依赖单事务
writeConcern 影响事务可见性与持久性
事务提交时的 writeConcern 决定“成功”意味着什么。默认 w=1(主节点写入即返回),但主节点宕机可能丢数据;设 w="majority" 才能保证多数节点落盘。
- 在
start_transaction()里通过write_concern=WriteConcern(w="majority")显式指定 - 注意:设
w="majority"会增加延迟,尤其跨地域副本集;测试环境可暂用w=1,生产务必评估 -
read_concern="majority"要配合使用,否则可能读到被回滚的中间状态
事务本身不难写,难的是时刻意识到它不是黑盒——session 传没传、部署支不支持、时间卡没卡住、写入到底落没落地,每个环节断掉,整件事就变成“以为在事务里,其实早提交了”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










