uniCloud事务必须在云函数中通过db.startTransaction()显式开启,仅支持单数据库内单次调用,需传入同一session实例,且仅阿里云/腾讯云Node.js 16+环境可用。

uni-app 本身不支持数据库事务,所有事务操作必须封装在云函数里,且仅限于单次云函数调用内 —— 这是硬性限制,不是配置问题。
uniCloud 云函数里怎么写事务?
UniCloud 的事务只支持 MongoDB 风格的 session.withTransaction(),但必须满足两个前提:使用阿里云或腾讯云(支付宝云暂不支持),且云函数运行环境为 Node.js 16+(HBuilderX 4.20+ 默认满足)。
- 事务必须显式开启
db.startTransaction(),不能靠自动提交 - 所有涉及事务的集合操作(
add、update、remove)必须传入同一session实例 - 事务内禁止跨数据库操作,所有集合必须属于同一个云数据库
- 事务超时默认 60 秒,若逻辑含 HTTP 请求或复杂计算,需手动控制执行时间,否则自动回滚
示例(阿里云环境):
exports.main = async (event, context) => {
const db = uniCloud.database({
throwOnNotFound: true
});
const session = db.startTransaction();
try {
const userRes = await db.collection('users').add(
{ name: event.name, balance: 100 },
{ session }
);
const logRes = await db.collection('logs').add(
{ action: 'create_user', userId: userRes.id },
{ session }
);
await session.commitTransaction();
return { success: true, userId: userRes.id };
} catch (e) {
await session.abortTransaction();
throw e;
}
};
为什么 uniCloud.transaction() 会报错?
常见错误是误用了已废弃的 API:uniCloud.transaction() 在 2025 年底已移除,现在统一走 db.startTransaction()。另外几个高频触发点:
- 在 H5 或小程序前端直接调用
uniCloud.database().startTransaction()→ 报错,前端无事务能力 - 云函数没指定 provider(如漏写
uniCloud.init({ provider: 'aliyun' }))→db.startTransaction返回undefined - 云函数部署时未勾选「启用事务支持」(HBuilderX 右键云函数目录 → 属性 → 勾选)→ 即使代码正确,运行时也静默失败
- 事务中混用非 session 操作,比如一个
update传了{ session },另一个remove没传 → 第二个操作不在事务内,提交后仍生效
事务失败后数据状态怎么判断?
事务失败不等于数据“没动”,而是取决于 abort 前是否已有部分操作落库。关键要记住:
- 事务未 commit 前,所有写操作对其他请求不可见(MVCC 隔离)
- 但若事务内某步已成功写入(比如第一个
add成功),而后续abort未执行(如 catch 块漏写或抛出新异常),那第一条数据就真写进去了 - 线上排查时,别只看云函数日志,要去 UniCloud 控制台「云数据库」→「操作日志」查实际执行记录,过滤
transactionId - 高并发场景下,避免在事务内做
get后再update(即“读-改-写”),应改用updateOne({ _id }, { $inc: { balance: -10 } })原子操作替代
事务不是银弹,尤其在跨端一致性要求高的场景(比如库存扣减+订单生成),得配合幂等 key 和补偿逻辑;单纯依赖 commit/abort 无法覆盖网络中断、云函数重启等边界情况。











