uni-app 使用事务时无法用 where 进行多条件 update

uni-app 使用事务时无法用 where 进行多条件 update

操作步骤:

  • 事务里面用了 where 进行多条件查询

预期结果:

  • 应该不会报错

实际结果:

{"code":"FUNCTIONS_EXECUTE_FAIL","message":"[FailedOperation.Abort] Abortfail. Retry your request, but if the problem persists,contact us.
Error: [FailedOperation.Abort] Abortfail. Retry your request, but if the problem persists,contact us.
    at Object.exports.E (/var/user/node_modules/@cloudbase/node-sdk/lib/utils/utils.js:24:12)
    at processReturn (/var/user/node_modules/@cloudbase/node-sdk/lib/utils/utils.js:43:19)
    at Object.exports.default (/var/user/node_modules/@cloudbase/node-sdk/lib/utils/httpRequest.js:377:20)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)","requestId":"bec8e1b27b094"}

bug描述:

在高并发抢购商品时,需要用到事务,在扣减库存的环节,为了避免订单超卖,用了 where 查询,但是报错:

{
    "code": "FUNCTIONS_EXECUTE_FAIL",
    "message": "[FailedOperation.Abort] Abortfail. Retry your request, but if the problem persists,contact us.
    Error: [FailedOperation.Abort] Abortfail. Retry your request, but if the problem persists,contact us.
        at Object.exports.E (/var/user/node_modules/@cloudbase/node-sdk/lib/utils/utils.js:24:12)
        at processReturn (/var/user/node_modules/@cloudbase/node-sdk/lib/utils/utils.js:43:19)
        at Object.exports.default (/var/user/node_modules/@cloudbase/node-sdk/lib/utils/httpRequest.js:377:20)
        at <anonymous>
        at process._tickCallback (internal/process/next_tick.js:188:7)",
    "requestId": "bec8e1b27b094"
}

以下是扣减库存的代码:

// 启动事务  
const transaction = await db.startTransaction();  
//减少商品库存  stock: dbCmd.gt(product.number) // TODO 限制库存大于下单库存量的才允许扣除库存  
const reduceRes = await db.collection('product')  
    .where({  
        _id: product_id, // 商品ID  
        stock: dbCmd.gte(1) // 限制库存大于下单量的才允许扣除库存  
    })  
    .update({  
        stock: dbCmd.inc(-1)  
    })  
if (reduceRes.updated === 0) {  
    await transaction.rollback()  
    return {  
        status: 0,  
        msg: '商品 1 秒前被抢完'  
    }  
}  
await transaction.commit()

更多关于uni-app 使用事务时无法用 where 进行多条件 update的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

你这更新!都没放事务里吧,这事务有用? const updateAAARes = await transaction.collection(‘account’).doc(‘aaa’).update({ amount: dbCmd.inc(-10) }) 要这样,而且对于修改和删除仅支持使用doc方法,不支持使用where方法。
可以先查找判断,再更新

更多关于uni-app 使用事务时无法用 where 进行多条件 update的实战教程也可以访问 https://www.itying.com/category-93-b0.html


根据错误信息和代码分析,这个问题是由于事务中的 where 条件查询与更新操作在云开发事务中的限制导致的。

在云开发的事务处理中,where 条件查询后直接进行 update 操作时,如果查询条件包含多个字段(特别是包含 dbCmd.gte(1) 这样的操作符条件),可能会导致事务失败并返回 FailedOperation.Abort 错误。

解决方案是使用事务的 get 方法先获取数据,然后在事务中直接使用 update 方法:

const transaction = await db.startTransaction();
const productCollection = transaction.collection('product');

// 先获取商品信息
const productDoc = await productCollection.doc(product_id).get();
const currentStock = productDoc.data[0].stock;

// 检查库存
if (currentStock < 1) {
    await transaction.rollback();
    return {
        status: 0,
        msg: '商品库存不足'
    };
}

// 直接更新库存
const reduceRes = await productCollection.doc(product_id).update({
    stock: dbCmd.inc(-1)
});

await transaction.commit();

或者使用事务的 update 方法配合文档引用:

const transaction = await db.startTransaction();
const productRef = transaction.collection('product').doc(product_id);

// 直接更新,通过返回值判断是否成功
const reduceRes = await productRef.update({
    stock: dbCmd.inc(-1)
});

// 检查更新是否成功
if (reduceRes.updated === 0) {
    await transaction.rollback();
    return {
        status: 0,
        msg: '商品库存不足'
    };
}

await transaction.commit();
回到顶部