事务操作
事务操作确保多个数据库操作要么全部成功,要么全部失败,保证数据的一致性。云开发支持数据库事务,并保证事务的 ACID 特性。
注意
目前数据库事务只支持在服务端运行,只有 node-sdk 支持事务。
使用场景
在大多数场景中,单文档完全可以满足需求。但在一些场景中,使用数据库事务的优势更明显:
- 从传统关系型数据库迁移到云开发:数据模型平滑迁移,业务代码改造成本低
- 涉及多个文档/多个集合的业务流程:保证一系列读写操作完全成功或者完全失败,防止出现中间态
支持的方法
事务流程方法
| API | 说明 |
|---|---|
| startTransaction | 发起事务 |
| commit | 提交事务 |
| rollback | 回滚事务 |
| runTransaction | 自动提交事务 |
事务中的数据操作
| API | 说明 |
|---|---|
| get | 查询文档 |
| add | 插入文档 |
| delete | 删除文档 |
| update | 更新文档 |
| set | 更新文档,文档不存在时,会自动创建 |
基础事务
参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| updateFunction | function | ✅ 是 | 事务更新函数,接收 transaction 参数 |
代码示例
const cloudbase = require('@cloudbase/node-sdk')
// 初始化数据库
const app = cloudbase.init({
env: 'your-env-id'
})
const db = app.database()
// 基础事务操作
const result = await db.runTransaction(async transaction => {
// 在事务中进行多个操作
const todoDoc = await transaction.collection('todos').doc('todo-id').get()
if (!todoDoc.data) {
throw new Error('待办事项不存在')
}
// 更新待办事项状态
await transaction.collection('todos').doc('todo-id').update({
data: {
completed: true,
completedAt: new Date()
}
})
// 更新用户统计
await transaction.collection('users').doc('user-id').update({
data: {
completedTodos: db.command.inc(1)
}
})
return { success: true }
})
console.log('事务执行结果:', result)
返回结果
{
result: { success: true }, // updateFunction 的返回值
errMsg: "runTransaction:ok"
}
复杂事务示例
清空购物车场景
以"清空购物车"的需求为例,展示 数据库事务在复杂业务场景中的使用:
// Node.js 环境
const cloudbase = require('@cloudbase/node-sdk')
// 初始化数据库
const app = cloudbase.init({
env: 'your-env-id'
})
const db = app.database()
exports.main = async (event, context) => {
const userId = 'user1'
const transaction = await db.startTransaction()
try {
const usersCollection = transaction.collection('users')
const goodsCollection = transaction.collection('goods')
// 1. 获取用户信息
const user = await usersCollection.doc(userId).get()
const { cart, balance } = user.data
// 2. 获取购物车数据和对应的商品信息
const goods = []
for (const { id } of cart) {
const good = await goodsCollection.doc(id).get()
goods.push(good.data)
}
let totalPrice = 0
for (let i = 0; i < cart.length; ++i) {
// 3. 计算购物车中的商品总价
totalPrice += cart[i].num * goods[i].price
// 4. 更新商品库存
await goodsCollection.doc(goods[i]._id).set({
inventory: goods[i].inventory - cart[i].num
})
}
// 5. 更新用户账户余额和清空购物车
await usersCollection.doc(userId).set({
balance: balance - totalPrice,
cart: []
})
await transaction.commit()
return { success: true, totalPrice }
} catch (error) {
await transaction.rollback()
throw error
}
}