gpt4 book ai didi

sql - Node.js SQL 竞态条件

转载 作者:太空宇宙 更新时间:2023-11-03 21:54:27 43 4
gpt4 key购买 nike

我想知道在执行 IO 时如何防止 NodeJS 中的竞争条件。我读了一点,每个人都坚持认为竞争条件是不可能的,因为 NodeJS 是单线程的。

让我们看一下下面的伪代码:

async decreaseUserBalance(userId, amount) {
const currentBalance = await sql.queryScalar('SELECT balance FROM user WHERE userid=?', [userId]);
await sql.query('UPDATE user SET balance = ? WHERE userid = ?', [currentBalance - amount, userId]);
}

假设连接的数据库 Node 负载很重,需要一些时间才能完成每个请求,并且每次用户单击某个商品的购买按钮时都会调用此函数。

当用户开始向此按钮发送垃圾邮件或让机器人发送购买请求时会发生什么?根据我的理解,第一个请求将执行 SELECT 查询,然后恢复执行。现在,由于用户正在向按钮发送垃圾邮件,因此下一个请求会进来,执行相同的功能。现在您有几个 SELECT 语句等待完成。现在,几个 select 语句完成执行并执行回调,因此现在有几个回调正在执行 UPDATE 语句,所有回调都具有相同的余额。这意味着,如果起始余额为 5,则所有余额都会从上次已知余额中减少 var amount。因此,基本上,同时执行此查询的频率并不重要,第一组请求都将从 SELECT 查询中获取相同的值,并将其更新为一些虚假值。

抱歉,如果我的解释有点模糊,但我相信这是一个非常现实的问题,我怀疑很多人都考虑到了。

为了解决这个问题,Node 是否支持互斥体之类的东西?据我所知,MongoDB 不支持表锁定,因此锁定只能是 SQL 的一个选项。

编辑:

我知道我可以在 1 个查询中完成这个示例,这样就可以解决它,但可以说这是不可能的。那你会如何解决这个问题呢?

编辑2:

好的,让我们看一下这个例子:

  async tryBuyItem(userId, itemId, price) {

//Do we still have enough balance?

const currentBalance = await sql.queryScalar('SELECT balance FROM user WHERE userid=?', [userId]);

if (currentBalance >= price) {
await sql.query('UPDATE user SET balance = balance - ? WHERE userid = ?', [price, userId]);
await sql.query('INSERT INTO user_items (userid, itemid) VALUES (?, ?)', [userId, itemId]);

return true;
} else {
return false;
}
}

最佳答案

你可以简单地做

sql.query('UPDATE user SET balance = balance - ? WHERE userid = ?', [amount, userId]);

这里没有竞争条件,也没有使用事务。

关于sql - Node.js SQL 竞态条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44841607/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com