事务需显式调用db.starttransaction()开启,腾讯云支持跨集合事务,阿里云仅限单集合且最多10次操作;批量更新应优先使用doc(id).update()而非where().update();事务内操作须轻量,并配置足够超时时间;生产环境应分批处理,每批独立事务、串行执行。

事务必须用 db.startTransaction() 显式开启
uniCloud 的事务不是自动包裹的,不调用 db.startTransaction() 就没有事务语义。哪怕你连续执行多个 update() 或 remove(),失败时前几条也不会回滚——这是最常被忽略的前提。
腾讯云版支持跨集合事务,阿里云版仅支持单集合内事务(且单事务最多 10 次操作)。所以写法上要先确认服务空间类型:
- 腾讯云:可安全在同一个
transaction实例里操作多个collection - 阿里云:只能对同一集合多次操作,且总次数 ≤ 10;跨集合必须拆成多个事务或放弃原子性
示例中若误在阿里云环境写跨集合事务,transaction.collection('orders').remove() 和 transaction.collection('logs').add() 会直接报错,而非静默失败。
批量更新别直接用 where().update(),优先走 doc(id).update()
用条件更新(如 where({ status: 0 }).update(...))本质是全表扫描,数据量一过千就容易超时或被限频。真实业务里,你要更新的往往是有明确 ID 列表的一批文档。
正确做法是把 ID 提前查出来,再循环调用 doc(id).update() —— 这个操作走索引,快且稳定:
- ID 列表建议一次不超过 50 个,实测成功率接近 100%
- 每条
doc(id).update()都是独立请求,但放在事务里就能保证全部成功或全部回滚 - 避免在事务里混用
where().update()和doc().update(),前者可能触发慢查询拖垮整个事务
错误写法:collection.where({ _id: db.command.in(idList) }).update(...) —— 看似批量,实际仍走条件匹配,性能和稳定性都不如逐个 doc()。
事务超时不是“等太久”,而是云函数硬性限制
uniCloud 默认云函数超时是 5 秒,而事务的 commit() 或 rollback() 必须在这个窗口内完成。一旦卡在某次数据库操作上(比如网络抖动、索引缺失导致慢查询),整个事务就会中断,且无法自动重试。
关键应对点:
- 事务内所有操作必须轻量:避免在事务里做 HTTP 请求、文件读写、复杂计算
- 提前在云函数配置里把超时时间拉到 15–30 秒(尤其处理 >20 条记录时)
-
catch块里必须显式调用transaction.rollback(),否则未提交的事务可能长期挂起,占用连接资源
注意:rollback() 本身也可能超时,所以要在 catch 里加 try/catch 包裹,防止 rollback 失败导致后续逻辑异常。
分批 + 事务 + 错误隔离才是生产级方案
真正上线的批量操作,从来不是“一个事务干完所有事”。而是把大任务切成小批次,每批各自开事务、各自 commit/rollback,互不影响。
比如要更新 500 条记录:
- 按每批 40 个 ID 分组(避开 50 上限,留缓冲)
- 每个批次启动独立
db.startTransaction() - 单批失败只影响本批,不影响其他批次,还能记录失败 ID 供人工干预
最容易被跳过的细节:批次之间要有 await 串行执行,别用 Promise.all 并发发起多个事务——云数据库连接池有限,并发事务太多反而触发限流,整体耗时更长。











