如何在MongoDb开始交易?

How to start a transaction in MongoDb?

我试图阻止对特定记录的并发请求,请参见以下示例:

function addMoney(orderID,orderID){
    const status = Database.getOrder(orderID);

    if (status === 1){
        return "Money Already Added";
    }

    Database.udateOrder(orderID, {status: 1});

    Database.addMoney(userID, 300);

    return true;
}

假设某人恰好在同一时间发出此请求,因此“状态”检查通过,他们将能够获得 Database.addMoney 运行 两次。

使用 MySQL,我会开始一个事务来锁定行,但不确定如何使用 MongoDB。

您可以像 MySQL 一样在 mongodb 中进行交易。考虑使用 id:123status:0order 文档。然后,您可以检查交易状态和 return 是否已付款或失败,以便添加货币文件和更新订单状态。 如果您遇到任何类似 Transaction numbers are only allowed on a replica set member or mongos 的问题, 可能会有所帮助。

In order to use transactions, you need a MongoDB replica set, and starting a replica set locally for development is an involved process. The new run-rs npm module makes starting replica sets easy.

const uri = 'mongodb://localhost:27017';
const dbName = 'myDB';
const MongoClient = require('mongodb').MongoClient;

async function main() {

    const client = new MongoClient(uri);
    await client.connect();
    const session = client.startSession();
    try {
        await session.withTransaction(async () => {
            const orders = client.db(dbName).collection('orders');
            const money = client.db(dbName).collection('money');
            let doc = await orders.findOne({orderID: 123});
            if (doc && doc.status === 1) {
                console.log("Money Already Added");
                return
            }
            await orders.updateOne({orderID: 123}, {'$set': {status: 1}});
            await money.insertOne({orderID: 123, userID: 100, amount: 300}, {session});
            console.log("Money added");
        });
        await session.commitTransaction();
    } catch (e) {
        console.log(e);
    } finally {
        await session.endSession();
        await client.close();
    }
}

main()

上面的代码可能需要改进,因为我无法在 MongoDB 上使用副本集对其进行测试。